From a9025ca8442f907bd5dffaa69e7f3890e6c38778 Mon Sep 17 00:00:00 2001 From: Samuel Tariku Date: Tue, 14 Oct 2025 04:39:27 +0300 Subject: [PATCH] feat: Add number_of_outcomes to odds market queries and models - Updated SQL queries to include number_of_outcomes in GetAllOdds, GetOddByID, GetOddsByEventID, and GetOddsByMarketID. - Modified data structures in domain and repository layers to accommodate number_of_outcomes. - Enhanced event models to track total odd outcomes. - Introduced new SQL scripts for development data seeding. --- db/dev_data/betfidel_data.sql | 221 ++++++++++++++++++ db/migrations/000001_fortune.up.sql | 24 +- db/query/events.sql | 18 +- db/query/odds.sql | 9 +- ...esync.sql => fix_autoincrement_desync.sql} | 0 gen/db/events.sql.go | 31 ++- gen/db/models.go | 79 ++++--- gen/db/odds.sql.go | 151 ++++++------ internal/domain/event.go | 8 + internal/domain/odds.go | 136 +++++------ internal/repository/event.go | 6 + internal/repository/odds.go | 63 ++--- internal/services/bet/service.go | 2 - internal/services/odds/service.go | 21 +- internal/services/result/service.go | 2 - internal/web_server/cron.go | 2 +- internal/web_server/handlers/cashier.go | 7 +- internal/web_server/handlers/event_handler.go | 5 + makefile | 14 ++ 19 files changed, 570 insertions(+), 229 deletions(-) create mode 100644 db/dev_data/betfidel_data.sql rename db/scripts/{003_fix_autoincrement_desync.sql => fix_autoincrement_desync.sql} (100%) diff --git a/db/dev_data/betfidel_data.sql b/db/dev_data/betfidel_data.sql new file mode 100644 index 0000000..29bc5e3 --- /dev/null +++ b/db/dev_data/betfidel_data.sql @@ -0,0 +1,221 @@ +CREATE EXTENSION IF NOT EXISTS pgcrypto; +DO $$ +DECLARE _admin_id bigint; +_manager_id bigint; +_company_wallet_id bigint; +_company_id bigint; +_branch_id bigint; +_branch_wallet_id bigint; +_cashier_id bigint; +BEGIN +INSERT INTO users ( + first_name, + last_name, + email, + phone_number, + password, + role, + email_verified, + phone_verified, + created_at, + updated_at, + suspended + ) +VALUES ( + 'Admin', + 'BetFidel', + 'admin.betfidel@gmail.com', + NULL, + crypt('password@123', gen_salt('bf'))::bytea, + 'admin', + TRUE, + FALSE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP, + FALSE + ) ON CONFLICT (email) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _admin_id; +INSERT INTO users ( + first_name, + last_name, + email, + phone_number, + password, + role, + email_verified, + phone_verified, + created_at, + updated_at, + suspended, + company_id + ) +VALUES ( + 'Manager', + 'BetFidel', + 'manager.betfidel@gmail.com', + NULL, + crypt('password@123', gen_salt('bf'))::bytea, + 'branch_manager', + TRUE, + FALSE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP, + FALSE, + _company_id + ) ON CONFLICT (email) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _manager_id; +INSERT INTO wallets ( + balance, + is_withdraw, + is_bettable, + is_transferable, + user_id, + type, + currency, + is_active, + created_at, + updated_at + ) +VALUES ( + 10000, + TRUE, + TRUE, + TRUE, + _admin_id, + 'company_wallet', + 'ETB', + TRUE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP + ) ON CONFLICT (user_id, type) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _company_wallet_id; +INSERT INTO companies ( + name, + slug, + admin_id, + wallet_id, + deducted_percentage, + is_active, + created_at, + updated_at + ) +VALUES ( + 'FidelBet', + 'betfidel', + _admin_id, + _company_wallet_id, + 0.15, + TRUE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP + ) ON CONFLICT (slug) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _company_id; +UPDATE users +SET company_id = _company_id +WHERE id = _admin_id; +INSERT INTO wallets ( + balance, + is_withdraw, + is_bettable, + is_transferable, + user_id, + type, + currency, + is_active, + created_at, + updated_at + ) +VALUES ( + 10000, + TRUE, + TRUE, + TRUE, + _admin_id, + 'branch_wallet', + 'ETB', + TRUE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP + ) ON CONFLICT (user_id, type) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _branch_wallet_id; +INSERT INTO branches ( + name, + location, + wallet_id, + branch_manager_id, + company_id, + is_self_owned, + profit_percent, + is_active, + created_at, + updated_at + ) +VALUES ( + 'Test Branch', + 'addis_ababa', + _branch_wallet_id, + _manager_id, + _company_id, + TRUE, + 0.10, + TRUE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP + ) ON CONFLICT (wallet_id) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _branch_id; +INSERT INTO users ( + first_name, + last_name, + email, + phone_number, + password, + role, + email_verified, + phone_verified, + created_at, + updated_at, + suspended, + company_id + ) +VALUES ( + 'Cashier', + 'BetFidel', + 'cashier.betfidel@gmail.com', + NULL, + crypt('password@123', gen_salt('bf'))::bytea, + 'cashier', + TRUE, + FALSE, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP, + FALSE, + _company_id + ) ON CONFLICT (email) DO +UPDATE +SET updated_at = EXCLUDED.updated_at +RETURNING id INTO STRICT _cashier_id; +INSERT INTO branch_cashiers (user_id, branch_id) +VALUES (_cashier_id, _branch_id); +RAISE NOTICE 'BETFIDEL_DEV_DATA (Admin ID: %, Company Wallet ID: %, Company ID: %)', +_admin_id, +_company_wallet_id, +_company_id; +RAISE NOTICE 'BETFIDEL_DEV_DATA (Branch ID: %, Branch Wallet ID: %, Manager ID: %)', +_branch_id, +_branch_wallet_id, +_manager_id; +RAISE NOTICE 'BETFIDEL_DEV_DATA (Cashier ID: %)', +_cashier_id; +END $$; \ No newline at end of file diff --git a/db/migrations/000001_fortune.up.sql b/db/migrations/000001_fortune.up.sql index e3c22c0..4b636ec 100644 --- a/db/migrations/000001_fortune.up.sql +++ b/db/migrations/000001_fortune.up.sql @@ -354,6 +354,7 @@ CREATE TABLE odds_market ( market_category TEXT NOT NULL, market_id BIGINT NOT NULL, raw_odds JSONB NOT NULL, + number_of_outcomes BIGINT NOT NULL, default_is_active BOOLEAN NOT NULL DEFAULT true, fetched_at TIMESTAMP DEFAULT now (), expires_at TIMESTAMP NOT NULL, @@ -693,15 +694,29 @@ SELECT e.*, e.default_winning_upper_limit ) AS winning_upper_limit, ces.updated_at as company_updated_at, - l.country_code as league_cc + l.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events e LEFT JOIN company_event_settings ces ON e.id = ces.event_id - JOIN leagues l ON l.id = e.league_id; + JOIN leagues l ON l.id = e.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = e.id; CREATE VIEW event_with_country AS SELECT events.*, - leagues.country_code as league_cc + leagues.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events - LEFT JOIN leagues ON leagues.id = events.league_id; + LEFT JOIN leagues ON leagues.id = events.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = events.id; CREATE VIEW odds_market_with_settings AS SELECT o.id, o.event_id, @@ -709,6 +724,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, diff --git a/db/query/events.sql b/db/query/events.sql index 84b10b8..d62b380 100644 --- a/db/query/events.sql +++ b/db/query/events.sql @@ -218,11 +218,18 @@ SELECT e.*, e.default_winning_upper_limit ) AS winning_upper_limit, ces.updated_at, - l.country_code as league_cc + l.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events e LEFT JOIN company_event_settings ces ON e.id = ces.event_id AND ces.company_id = $1 JOIN leagues l ON l.id = e.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = e.id WHERE ( is_live = sqlc.narg('is_live') OR sqlc.narg('is_live') IS NULL @@ -292,11 +299,18 @@ SELECT e.*, e.default_winning_upper_limit ) AS winning_upper_limit, ces.updated_at, - l.country_code as league_cc + l.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events e LEFT JOIN company_event_settings ces ON e.id = ces.event_id AND ces.company_id = $2 JOIN leagues l ON l.id = e.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = e.id WHERE e.id = $1 LIMIT 1; -- name: GetSportAndLeagueIDs :one diff --git a/db/query/odds.sql b/db/query/odds.sql index 8950868..6979426 100644 --- a/db/query/odds.sql +++ b/db/query/odds.sql @@ -5,6 +5,7 @@ INSERT INTO odds_market ( market_name, market_category, market_id, + number_of_outcomes, raw_odds, fetched_at, expires_at @@ -17,13 +18,15 @@ VALUES ( $5, $6, $7, - $8 + $8, + $9 ) ON CONFLICT (event_id, market_id) DO UPDATE SET market_type = EXCLUDED.market_type, market_name = EXCLUDED.market_name, market_category = EXCLUDED.market_category, raw_odds = EXCLUDED.raw_odds, + number_of_outcomes = EXCLUDED.number_of_outcomes, fetched_at = EXCLUDED.fetched_at, expires_at = EXCLUDED.expires_at; -- name: SaveOddSettings :exec @@ -48,6 +51,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -75,6 +79,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -94,6 +99,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -129,6 +135,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, diff --git a/db/scripts/003_fix_autoincrement_desync.sql b/db/scripts/fix_autoincrement_desync.sql similarity index 100% rename from db/scripts/003_fix_autoincrement_desync.sql rename to db/scripts/fix_autoincrement_desync.sql diff --git a/gen/db/events.sql.go b/gen/db/events.sql.go index 380793e..767a4e2 100644 --- a/gen/db/events.sql.go +++ b/gen/db/events.sql.go @@ -22,7 +22,7 @@ func (q *Queries) DeleteEvent(ctx context.Context, id int64) error { } const GetAllEvents = `-- name: GetAllEvents :many -SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc +SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes FROM event_with_country WHERE ( is_live = $1 @@ -129,6 +129,7 @@ func (q *Queries) GetAllEvents(ctx context.Context, arg GetAllEventsParams) ([]E &i.DefaultWinningUpperLimit, &i.IsMonitored, &i.LeagueCc, + &i.TotalOutcomes, ); err != nil { return nil, err } @@ -141,7 +142,7 @@ func (q *Queries) GetAllEvents(ctx context.Context, arg GetAllEventsParams) ([]E } const GetEventByID = `-- name: GetEventByID :one -SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc +SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes FROM event_with_country WHERE id = $1 LIMIT 1 @@ -179,12 +180,13 @@ func (q *Queries) GetEventByID(ctx context.Context, id int64) (EventWithCountry, &i.DefaultWinningUpperLimit, &i.IsMonitored, &i.LeagueCc, + &i.TotalOutcomes, ) return i, err } const GetEventBySourceID = `-- name: GetEventBySourceID :one -SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc +SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes FROM event_with_country WHERE source_event_id = $1 AND source = $2 @@ -227,6 +229,7 @@ func (q *Queries) GetEventBySourceID(ctx context.Context, arg GetEventBySourceID &i.DefaultWinningUpperLimit, &i.IsMonitored, &i.LeagueCc, + &i.TotalOutcomes, ) return i, err } @@ -241,11 +244,18 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te e.default_winning_upper_limit ) AS winning_upper_limit, ces.updated_at, - l.country_code as league_cc + l.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events e LEFT JOIN company_event_settings ces ON e.id = ces.event_id AND ces.company_id = $2 JOIN leagues l ON l.id = e.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = e.id WHERE e.id = $1 LIMIT 1 ` @@ -289,6 +299,7 @@ type GetEventWithSettingByIDRow struct { WinningUpperLimit int64 `json:"winning_upper_limit"` UpdatedAt_2 pgtype.Timestamp `json:"updated_at_2"` LeagueCc pgtype.Text `json:"league_cc"` + TotalOutcomes int64 `json:"total_outcomes"` } func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithSettingByIDParams) (GetEventWithSettingByIDRow, error) { @@ -328,6 +339,7 @@ func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithS &i.WinningUpperLimit, &i.UpdatedAt_2, &i.LeagueCc, + &i.TotalOutcomes, ) return i, err } @@ -342,11 +354,18 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te e.default_winning_upper_limit ) AS winning_upper_limit, ces.updated_at, - l.country_code as league_cc + l.country_code as league_cc, + COALESCE(om.total_outcomes, 0) AS total_outcomes FROM events e LEFT JOIN company_event_settings ces ON e.id = ces.event_id AND ces.company_id = $1 JOIN leagues l ON l.id = e.league_id + LEFT JOIN ( + SELECT event_id, + SUM(number_of_outcomes) AS total_outcomes + FROM odds_market + GROUP BY event_id + ) om ON om.event_id = e.id WHERE ( is_live = $2 OR $2 IS NULL @@ -449,6 +468,7 @@ type GetEventsWithSettingsRow struct { WinningUpperLimit int64 `json:"winning_upper_limit"` UpdatedAt_2 pgtype.Timestamp `json:"updated_at_2"` LeagueCc pgtype.Text `json:"league_cc"` + TotalOutcomes int64 `json:"total_outcomes"` } func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSettingsParams) ([]GetEventsWithSettingsRow, error) { @@ -509,6 +529,7 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe &i.WinningUpperLimit, &i.UpdatedAt_2, &i.LeagueCc, + &i.TotalOutcomes, ); err != nil { return nil, err } diff --git a/gen/db/models.go b/gen/db/models.go index 62182e5..f2cbd47 100644 --- a/gen/db/models.go +++ b/gen/db/models.go @@ -376,6 +376,7 @@ type EventWithCountry struct { DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"` IsMonitored bool `json:"is_monitored"` LeagueCc pgtype.Text `json:"league_cc"` + TotalOutcomes int64 `json:"total_outcomes"` } type EventWithSetting struct { @@ -412,6 +413,7 @@ type EventWithSetting struct { WinningUpperLimit int64 `json:"winning_upper_limit"` CompanyUpdatedAt pgtype.Timestamp `json:"company_updated_at"` LeagueCc pgtype.Text `json:"league_cc"` + TotalOutcomes int64 `json:"total_outcomes"` } type ExchangeRate struct { @@ -502,49 +504,52 @@ type OddHistory struct { } type OddsMarket struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - RawOdds []byte `json:"raw_odds"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + RawOdds []byte `json:"raw_odds"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` } type OddsMarketWithEvent struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - RawOdds []byte `json:"raw_odds"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - IsMonitored bool `json:"is_monitored"` - IsLive bool `json:"is_live"` - Status string `json:"status"` - Source string `json:"source"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + RawOdds []byte `json:"raw_odds"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + IsMonitored bool `json:"is_monitored"` + IsLive bool `json:"is_live"` + Status string `json:"status"` + Source string `json:"source"` } type OddsMarketWithSetting struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - CompanyID pgtype.Int8 `json:"company_id"` - IsActive bool `json:"is_active"` - RawOdds []byte `json:"raw_odds"` - UpdatedAt pgtype.Timestamp `json:"updated_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + CompanyID pgtype.Int8 `json:"company_id"` + IsActive bool `json:"is_active"` + RawOdds []byte `json:"raw_odds"` + UpdatedAt pgtype.Timestamp `json:"updated_at"` } type Otp struct { diff --git a/gen/db/odds.sql.go b/gen/db/odds.sql.go index e7c687e..632f03c 100644 --- a/gen/db/odds.sql.go +++ b/gen/db/odds.sql.go @@ -48,7 +48,7 @@ func (q *Queries) DeleteOddsForEvent(ctx context.Context, eventID int64) error { } const GetAllOdds = `-- name: GetAllOdds :many -SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source +SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source FROM odds_market_with_event LIMIT $2 OFFSET $1 ` @@ -75,6 +75,7 @@ func (q *Queries) GetAllOdds(ctx context.Context, arg GetAllOddsParams) ([]OddsM &i.MarketCategory, &i.MarketID, &i.RawOdds, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -100,6 +101,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -120,19 +122,20 @@ type GetAllOddsWithSettingsParams struct { } type GetAllOddsWithSettingsRow struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - CompanyID pgtype.Int8 `json:"company_id"` - IsActive bool `json:"is_active"` - RawOdds []byte `json:"raw_odds"` - UpdatedAt pgtype.Timestamp `json:"updated_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + CompanyID pgtype.Int8 `json:"company_id"` + IsActive bool `json:"is_active"` + RawOdds []byte `json:"raw_odds"` + UpdatedAt pgtype.Timestamp `json:"updated_at"` } func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWithSettingsParams) ([]GetAllOddsWithSettingsRow, error) { @@ -151,6 +154,7 @@ func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWith &i.MarketName, &i.MarketCategory, &i.MarketID, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -170,7 +174,7 @@ func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWith } const GetOddByID = `-- name: GetOddByID :one -SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source +SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source FROM odds_market_with_event WHERE id = $1 ` @@ -186,6 +190,7 @@ func (q *Queries) GetOddByID(ctx context.Context, id int64) (OddsMarketWithEvent &i.MarketCategory, &i.MarketID, &i.RawOdds, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -198,7 +203,7 @@ func (q *Queries) GetOddByID(ctx context.Context, id int64) (OddsMarketWithEvent } const GetOddsByEventID = `-- name: GetOddsByEventID :many -SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source +SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source FROM odds_market_with_event WHERE event_id = $1 AND ( @@ -249,6 +254,7 @@ func (q *Queries) GetOddsByEventID(ctx context.Context, arg GetOddsByEventIDPara &i.MarketCategory, &i.MarketID, &i.RawOdds, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -268,7 +274,7 @@ func (q *Queries) GetOddsByEventID(ctx context.Context, arg GetOddsByEventIDPara } const GetOddsByMarketID = `-- name: GetOddsByMarketID :one -SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source +SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source FROM odds_market_with_event WHERE market_id = $1 AND event_id = $2 @@ -290,6 +296,7 @@ func (q *Queries) GetOddsByMarketID(ctx context.Context, arg GetOddsByMarketIDPa &i.MarketCategory, &i.MarketID, &i.RawOdds, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -308,6 +315,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -330,19 +338,20 @@ type GetOddsWithSettingsByEventIDParams struct { } type GetOddsWithSettingsByEventIDRow struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - CompanyID pgtype.Int8 `json:"company_id"` - IsActive bool `json:"is_active"` - RawOdds []byte `json:"raw_odds"` - UpdatedAt pgtype.Timestamp `json:"updated_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + CompanyID pgtype.Int8 `json:"company_id"` + IsActive bool `json:"is_active"` + RawOdds []byte `json:"raw_odds"` + UpdatedAt pgtype.Timestamp `json:"updated_at"` } func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsWithSettingsByEventIDParams) ([]GetOddsWithSettingsByEventIDRow, error) { @@ -366,6 +375,7 @@ func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsW &i.MarketName, &i.MarketCategory, &i.MarketID, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -391,6 +401,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -410,19 +421,20 @@ type GetOddsWithSettingsByIDParams struct { } type GetOddsWithSettingsByIDRow struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - CompanyID pgtype.Int8 `json:"company_id"` - IsActive bool `json:"is_active"` - RawOdds []byte `json:"raw_odds"` - UpdatedAt pgtype.Timestamp `json:"updated_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + CompanyID pgtype.Int8 `json:"company_id"` + IsActive bool `json:"is_active"` + RawOdds []byte `json:"raw_odds"` + UpdatedAt pgtype.Timestamp `json:"updated_at"` } func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSettingsByIDParams) (GetOddsWithSettingsByIDRow, error) { @@ -435,6 +447,7 @@ func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSe &i.MarketName, &i.MarketCategory, &i.MarketID, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -453,6 +466,7 @@ SELECT o.id, o.market_name, o.market_category, o.market_id, + o.number_of_outcomes, o.default_is_active, o.fetched_at, o.expires_at, @@ -474,19 +488,20 @@ type GetOddsWithSettingsByMarketIDParams struct { } type GetOddsWithSettingsByMarketIDRow struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - DefaultIsActive bool `json:"default_is_active"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` - CompanyID pgtype.Int8 `json:"company_id"` - IsActive bool `json:"is_active"` - RawOdds []byte `json:"raw_odds"` - UpdatedAt pgtype.Timestamp `json:"updated_at"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + DefaultIsActive bool `json:"default_is_active"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` + CompanyID pgtype.Int8 `json:"company_id"` + IsActive bool `json:"is_active"` + RawOdds []byte `json:"raw_odds"` + UpdatedAt pgtype.Timestamp `json:"updated_at"` } func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOddsWithSettingsByMarketIDParams) (GetOddsWithSettingsByMarketIDRow, error) { @@ -499,6 +514,7 @@ func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOdds &i.MarketName, &i.MarketCategory, &i.MarketID, + &i.NumberOfOutcomes, &i.DefaultIsActive, &i.FetchedAt, &i.ExpiresAt, @@ -517,6 +533,7 @@ INSERT INTO odds_market ( market_name, market_category, market_id, + number_of_outcomes, raw_odds, fetched_at, expires_at @@ -529,26 +546,29 @@ VALUES ( $5, $6, $7, - $8 + $8, + $9 ) ON CONFLICT (event_id, market_id) DO UPDATE SET market_type = EXCLUDED.market_type, market_name = EXCLUDED.market_name, market_category = EXCLUDED.market_category, raw_odds = EXCLUDED.raw_odds, + number_of_outcomes = EXCLUDED.number_of_outcomes, fetched_at = EXCLUDED.fetched_at, expires_at = EXCLUDED.expires_at ` type InsertOddsMarketParams struct { - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - RawOdds []byte `json:"raw_odds"` - FetchedAt pgtype.Timestamp `json:"fetched_at"` - ExpiresAt pgtype.Timestamp `json:"expires_at"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + RawOdds []byte `json:"raw_odds"` + FetchedAt pgtype.Timestamp `json:"fetched_at"` + ExpiresAt pgtype.Timestamp `json:"expires_at"` } func (q *Queries) InsertOddsMarket(ctx context.Context, arg InsertOddsMarketParams) error { @@ -558,6 +578,7 @@ func (q *Queries) InsertOddsMarket(ctx context.Context, arg InsertOddsMarketPara arg.MarketName, arg.MarketCategory, arg.MarketID, + arg.NumberOfOutcomes, arg.RawOdds, arg.FetchedAt, arg.ExpiresAt, diff --git a/internal/domain/event.go b/internal/domain/event.go index de5ac3a..f46032d 100644 --- a/internal/domain/event.go +++ b/internal/domain/event.go @@ -120,6 +120,7 @@ type BaseEvent struct { StartTime time.Time Source EventSource Status EventStatus + TotalOddOutcomes int64 IsMonitored bool DefaultIsFeatured bool DefaultIsActive bool @@ -149,6 +150,7 @@ type BaseEventRes struct { StartTime time.Time `json:"start_time"` Source EventSource `json:"source"` Status EventStatus `json:"status"` + TotalOddOutcomes int64 `json:"total_odd_outcomes"` IsMonitored bool `json:"is_monitored"` DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsActive bool `json:"default_is_active"` @@ -178,6 +180,7 @@ type EventWithSettings struct { StartTime time.Time Source EventSource Status EventStatus + TotalOddOutcomes int64 IsMonitored bool IsFeatured bool IsActive bool @@ -231,6 +234,7 @@ type EventWithSettingsRes struct { StartTime time.Time `json:"start_time"` Source EventSource `json:"source"` Status EventStatus `json:"status"` + TotalOddOutcomes int64 `json:"total_odd_outcomes"` IsMonitored bool `json:"is_monitored"` IsFeatured bool `json:"is_featured"` IsActive bool `json:"is_active"` @@ -332,6 +336,7 @@ func ConvertDBEvent(event dbgen.EventWithCountry) BaseEvent { StartTime: event.StartTime.Time.UTC(), Source: EventSource(event.Source), Status: EventStatus(event.Status), + TotalOddOutcomes: event.TotalOutcomes, DefaultIsFeatured: event.DefaultIsFeatured, IsMonitored: event.IsMonitored, DefaultIsActive: event.DefaultIsActive, @@ -422,6 +427,7 @@ func ConvertDBEventWithSetting(event dbgen.EventWithSetting) EventWithSettings { StartTime: event.StartTime.Time.UTC(), Source: EventSource(event.Source), Status: EventStatus(event.Status), + TotalOddOutcomes: event.TotalOutcomes, IsFeatured: event.IsFeatured, IsMonitored: event.IsMonitored, IsActive: event.IsActive, @@ -498,6 +504,7 @@ func ConvertEventRes(event BaseEvent) BaseEventRes { StartTime: event.StartTime.UTC(), Source: EventSource(event.Source), Status: EventStatus(event.Status), + TotalOddOutcomes: event.TotalOddOutcomes, DefaultIsFeatured: event.DefaultIsFeatured, IsMonitored: event.IsMonitored, DefaultIsActive: event.DefaultIsActive, @@ -537,6 +544,7 @@ func ConvertEventWitSettingRes(event EventWithSettings) EventWithSettingsRes { StartTime: event.StartTime.UTC(), Source: EventSource(event.Source), Status: EventStatus(event.Status), + TotalOddOutcomes: event.TotalOddOutcomes, IsFeatured: event.IsFeatured, IsMonitored: event.IsMonitored, IsActive: event.IsActive, diff --git a/internal/domain/odds.go b/internal/domain/odds.go index 27ac23c..9d6ff2f 100644 --- a/internal/domain/odds.go +++ b/internal/domain/odds.go @@ -9,42 +9,45 @@ import ( ) type CreateOddMarket struct { - EventID int64 - MarketCategory string - MarketType string - MarketName string - MarketID int64 - UpdatedAt time.Time - Odds []map[string]interface{} + EventID int64 + MarketCategory string + MarketType string + MarketName string + MarketID int64 + NumberOfOutcomes int64 + UpdatedAt time.Time + Odds []map[string]interface{} } type OddMarket struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - RawOdds []json.RawMessage `json:"raw_odds"` - FetchedAt time.Time `json:"fetched_at"` - ExpiresAt time.Time `json:"expires_at"` - DefaultIsActive bool `json:"is_active"` - IsMonitored bool `json:"is_monitored"` - IsLive bool `json:"is_live"` - Status EventStatus `json:"status"` - Source EventSource `json:"source"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + RawOdds []json.RawMessage `json:"raw_odds"` + FetchedAt time.Time `json:"fetched_at"` + ExpiresAt time.Time `json:"expires_at"` + DefaultIsActive bool `json:"is_active"` + IsMonitored bool `json:"is_monitored"` + IsLive bool `json:"is_live"` + Status EventStatus `json:"status"` + Source EventSource `json:"source"` } type OddMarketWithSettings struct { - ID int64 `json:"id"` - EventID int64 `json:"event_id"` - MarketType string `json:"market_type"` - MarketName string `json:"market_name"` - MarketCategory string `json:"market_category"` - MarketID int64 `json:"market_id"` - RawOdds []json.RawMessage `json:"raw_odds"` - FetchedAt time.Time `json:"fetched_at"` - ExpiresAt time.Time `json:"expires_at"` - IsActive bool `json:"is_active"` + ID int64 `json:"id"` + EventID int64 `json:"event_id"` + MarketType string `json:"market_type"` + MarketName string `json:"market_name"` + MarketCategory string `json:"market_category"` + MarketID int64 `json:"market_id"` + NumberOfOutcomes int64 `json:"number_of_outcomes"` + RawOdds []json.RawMessage `json:"raw_odds"` + FetchedAt time.Time `json:"fetched_at"` + ExpiresAt time.Time `json:"expires_at"` + IsActive bool `json:"is_active"` } type OddMarketSettings struct { @@ -78,8 +81,8 @@ type CreateOddMarketSettingsReq struct { } type UpdateGlobalOddMarketSettingsReq struct { - OddMarketID int64 `json:"odd_market_id"` - IsActive *bool `json:"is_active,omitempty"` + OddMarketID int64 `json:"odd_market_id"` + IsActive *bool `json:"is_active,omitempty"` } type RawOddsByMarketID struct { @@ -112,20 +115,21 @@ func ConvertDBOddMarket(oddMarket dbgen.OddsMarketWithEvent) (OddMarket, error) rawOdds = []json.RawMessage{} // explicit empty slice } return OddMarket{ - ID: oddMarket.ID, - EventID: oddMarket.EventID, - MarketType: oddMarket.MarketType, - MarketName: oddMarket.MarketName, - MarketCategory: oddMarket.MarketCategory, - MarketID: oddMarket.MarketID, - RawOdds: rawOdds, - FetchedAt: oddMarket.FetchedAt.Time, - ExpiresAt: oddMarket.ExpiresAt.Time, - DefaultIsActive: oddMarket.DefaultIsActive, - IsMonitored: oddMarket.IsMonitored, - IsLive: oddMarket.IsLive, - Status: EventStatus(oddMarket.Status), - Source: EventSource(oddMarket.Source), + ID: oddMarket.ID, + EventID: oddMarket.EventID, + MarketType: oddMarket.MarketType, + MarketName: oddMarket.MarketName, + MarketCategory: oddMarket.MarketCategory, + MarketID: oddMarket.MarketID, + NumberOfOutcomes: oddMarket.NumberOfOutcomes, + RawOdds: rawOdds, + FetchedAt: oddMarket.FetchedAt.Time, + ExpiresAt: oddMarket.ExpiresAt.Time, + DefaultIsActive: oddMarket.DefaultIsActive, + IsMonitored: oddMarket.IsMonitored, + IsLive: oddMarket.IsLive, + Status: EventStatus(oddMarket.Status), + Source: EventSource(oddMarket.Source), }, nil } @@ -148,14 +152,15 @@ func ConvertCreateOddMarket(oddMarket CreateOddMarket) (dbgen.InsertOddsMarketPa } return dbgen.InsertOddsMarketParams{ - EventID: oddMarket.EventID, - MarketType: oddMarket.MarketType, - MarketName: oddMarket.MarketName, - MarketCategory: oddMarket.MarketCategory, - MarketID: oddMarket.MarketID, - RawOdds: rawOddsBytes, - FetchedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, - ExpiresAt: pgtype.Timestamp{Time: (time.Now()).Add(time.Hour), Valid: true}, + EventID: oddMarket.EventID, + MarketType: oddMarket.MarketType, + MarketName: oddMarket.MarketName, + MarketCategory: oddMarket.MarketCategory, + MarketID: oddMarket.MarketID, + NumberOfOutcomes: oddMarket.NumberOfOutcomes, + RawOdds: rawOddsBytes, + FetchedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, + ExpiresAt: pgtype.Timestamp{Time: (time.Now()).Add(time.Hour), Valid: true}, }, nil } @@ -182,16 +187,17 @@ func ConvertDBOddMarketWithSetting(oms dbgen.OddsMarketWithSetting) (OddMarketWi rawOdds = []json.RawMessage{} // explicit empty slice } return OddMarketWithSettings{ - ID: oms.ID, - EventID: oms.EventID, - MarketType: oms.MarketType, - MarketName: oms.MarketName, - MarketCategory: oms.MarketCategory, - MarketID: oms.MarketID, - RawOdds: rawOdds, - FetchedAt: oms.FetchedAt.Time, - ExpiresAt: oms.ExpiresAt.Time, - IsActive: oms.IsActive, + ID: oms.ID, + EventID: oms.EventID, + MarketType: oms.MarketType, + MarketName: oms.MarketName, + MarketCategory: oms.MarketCategory, + MarketID: oms.MarketID, + NumberOfOutcomes: oms.NumberOfOutcomes, + RawOdds: rawOdds, + FetchedAt: oms.FetchedAt.Time, + ExpiresAt: oms.ExpiresAt.Time, + IsActive: oms.IsActive, }, nil } diff --git a/internal/repository/event.go b/internal/repository/event.go index dca45ff..fcc20c5 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -126,6 +126,9 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt StartTime: event.StartTime.Time.UTC(), Source: domain.EventSource(event.Source), Status: domain.EventStatus(event.Status), + TotalOddOutcomes: event.TotalOutcomes, + SourceEventID: event.SourceEventID, + WinningUpperLimit: event.WinningUpperLimit, IsFeatured: event.IsFeatured, IsMonitored: event.IsMonitored, IsActive: event.IsActive, @@ -207,6 +210,9 @@ func (s *Store) GetEventWithSettingByID(ctx context.Context, ID int64, companyID StartTime: event.StartTime.Time.UTC(), Source: domain.EventSource(event.Source), Status: domain.EventStatus(event.Status), + TotalOddOutcomes: event.TotalOutcomes, + SourceEventID: event.SourceEventID, + WinningUpperLimit: event.WinningUpperLimit, IsFeatured: event.IsFeatured, IsMonitored: event.IsMonitored, IsActive: event.IsActive, diff --git a/internal/repository/odds.go b/internal/repository/odds.go index 009e301..8dd7c7f 100644 --- a/internal/repository/odds.go +++ b/internal/repository/odds.go @@ -180,16 +180,17 @@ func (s *Store) GetOddsWithSettingsByMarketID(ctx context.Context, marketID int6 } converted := domain.OddMarketWithSettings{ - ID: odds.ID, - EventID: odds.EventID, - MarketType: odds.MarketType, - MarketName: odds.MarketName, - MarketCategory: odds.MarketCategory, - MarketID: odds.MarketID, - RawOdds: rawOdds, - FetchedAt: odds.FetchedAt.Time, - ExpiresAt: odds.ExpiresAt.Time, - IsActive: odds.IsActive, + ID: odds.ID, + EventID: odds.EventID, + MarketType: odds.MarketType, + MarketName: odds.MarketName, + MarketCategory: odds.MarketCategory, + MarketID: odds.MarketID, + NumberOfOutcomes: odds.NumberOfOutcomes, + RawOdds: rawOdds, + FetchedAt: odds.FetchedAt.Time, + ExpiresAt: odds.ExpiresAt.Time, + IsActive: odds.IsActive, } return converted, nil } @@ -221,16 +222,17 @@ func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID } converted := domain.OddMarketWithSettings{ - ID: odds.ID, - EventID: odds.EventID, - MarketType: odds.MarketType, - MarketName: odds.MarketName, - MarketCategory: odds.MarketCategory, - MarketID: odds.MarketID, - RawOdds: rawOdds, - FetchedAt: odds.FetchedAt.Time, - ExpiresAt: odds.ExpiresAt.Time, - IsActive: odds.IsActive, + ID: odds.ID, + EventID: odds.EventID, + MarketType: odds.MarketType, + MarketName: odds.MarketName, + MarketCategory: odds.MarketCategory, + MarketID: odds.MarketID, + NumberOfOutcomes: odds.NumberOfOutcomes, + RawOdds: rawOdds, + FetchedAt: odds.FetchedAt.Time, + ExpiresAt: odds.ExpiresAt.Time, + IsActive: odds.IsActive, } return converted, nil @@ -287,16 +289,17 @@ func (s *Store) GetOddsWithSettingsByEventID(ctx context.Context, eventID int64, } result[i] = domain.OddMarketWithSettings{ - ID: o.ID, - EventID: o.EventID, - MarketType: o.MarketType, - MarketName: o.MarketName, - MarketCategory: o.MarketCategory, - MarketID: o.MarketID, - RawOdds: rawOdds, - FetchedAt: o.FetchedAt.Time, - ExpiresAt: o.ExpiresAt.Time, - IsActive: o.IsActive, + ID: o.ID, + EventID: o.EventID, + MarketType: o.MarketType, + MarketName: o.MarketName, + MarketCategory: o.MarketCategory, + MarketID: o.MarketID, + NumberOfOutcomes: o.NumberOfOutcomes, + RawOdds: rawOdds, + FetchedAt: o.FetchedAt.Time, + ExpiresAt: o.ExpiresAt.Time, + IsActive: o.IsActive, } } diff --git a/internal/services/bet/service.go b/internal/services/bet/service.go index ab1f033..d6ff26a 100644 --- a/internal/services/bet/service.go +++ b/internal/services/bet/service.go @@ -1236,8 +1236,6 @@ func (s *Service) ProcessBetCashback(ctx context.Context) error { zap.Int64("userID", bet.UserID), zap.Error(err)) } - - // Add a notification here } return nil } diff --git a/internal/services/odds/service.go b/internal/services/odds/service.go index dcc1004..0cf6574 100644 --- a/internal/services/odds/service.go +++ b/internal/services/odds/service.go @@ -557,13 +557,14 @@ func (s *ServiceImpl) storeSection(ctx context.Context, eventID int64, fi, secti } marketRecord := domain.CreateOddMarket{ - EventID: eventID, - MarketCategory: sectionName, - MarketType: marketType, - MarketName: market.Name, - MarketID: marketIDint, - UpdatedAt: updatedAt, - Odds: marketOdds, + EventID: eventID, + MarketCategory: sectionName, + MarketType: marketType, + MarketName: market.Name, + MarketID: marketIDint, + NumberOfOutcomes: int64(len(market.Odds)), + UpdatedAt: updatedAt, + Odds: marketOdds, // bwin won't reach this code so bet365 is hardcoded for now } @@ -676,8 +677,8 @@ func (s *ServiceImpl) SaveOddsSetting(ctx context.Context, odd domain.CreateOddM return s.store.SaveOddsSetting(ctx, odd) } -func (s *ServiceImpl) UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error { - return s.store.UpdateGlobalOddsSetting(ctx, odd); +func (s *ServiceImpl) UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error { + return s.store.UpdateGlobalOddsSetting(ctx, odd) } func (s *ServiceImpl) SaveOddsSettingReq(ctx context.Context, companyID int64, req domain.CreateOddMarketSettingsReq) error { @@ -749,7 +750,7 @@ func (s *ServiceImpl) DeleteAllCompanyOddsSetting(ctx context.Context, companyID return s.store.DeleteAllCompanyOddsSetting(ctx, companyID) } -func (s *ServiceImpl) DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error{ +func (s *ServiceImpl) DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error { return s.store.DeleteCompanyOddsSettingByOddMarketID(ctx, companyID, oddMarketID) } diff --git a/internal/services/result/service.go b/internal/services/result/service.go index e5f09b4..1a12d1f 100644 --- a/internal/services/result/service.go +++ b/internal/services/result/service.go @@ -262,7 +262,6 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error { eventLogger := s.mongoLogger.With( zap.Int64("eventID", event.ID), ) - result, err := s.FetchB365Result(ctx, event.SourceEventID) if err != nil { if err == ErrEventIsNotActive { @@ -457,7 +456,6 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error { return nil } - func (s *Service) CheckAndUpdateExpiredB365Events(ctx context.Context) (int64, error) { events, _, err := s.repo.GetAllEvents(ctx, domain.EventFilter{ LastStartTime: domain.ValidTime{ diff --git a/internal/web_server/cron.go b/internal/web_server/cron.go index 13019f3..9b0b21a 100644 --- a/internal/web_server/cron.go +++ b/internal/web_server/cron.go @@ -96,7 +96,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S } for _, job := range schedule { - // job.task() + job.task() if _, err := c.AddFunc(job.spec, job.task); err != nil { mongoLogger.Error("Failed to schedule data fetching cron job", zap.Error(err), diff --git a/internal/web_server/handlers/cashier.go b/internal/web_server/handlers/cashier.go index 139f4a4..1efb392 100644 --- a/internal/web_server/handlers/cashier.go +++ b/internal/web_server/handlers/cashier.go @@ -227,11 +227,8 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error { return fiber.NewError(fiber.StatusBadRequest, errMsg) } - cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), domain.UserFilter{ - Query: searchString, - CreatedBefore: createdBefore, - CreatedAfter: createdAfter, - }) + cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), filter) + if err != nil { h.mongoLoggerSvc.Error("failed to get all cashiers", zap.Int("status_code", fiber.StatusInternalServerError), diff --git a/internal/web_server/handlers/event_handler.go b/internal/web_server/handlers/event_handler.go index bad2fdf..533c76f 100644 --- a/internal/web_server/handlers/event_handler.go +++ b/internal/web_server/handlers/event_handler.go @@ -285,6 +285,11 @@ func (h *Handler) GetTenantUpcomingEvents(c *fiber.Ctx) error { Value: firstStartTimeParsed, Valid: true, } + } else { + firstStartTime = domain.ValidTime{ + Value: time.Now(), + Valid: true, + } } lastStartTimeQuery := c.Query("last_start_time") diff --git a/makefile b/makefile index ee00452..936aee9 100644 --- a/makefile +++ b/makefile @@ -69,6 +69,20 @@ seed_data: echo "Seeding $$file..."; \ cat $$file | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh; \ done +.PHONY: seed_dev_data +seed_dev_data: + @echo "Waiting for PostgreSQL to be ready..." + @until docker exec fortunebet-backend-postgres-1 pg_isready -U root -d gh; do \ + echo "PostgreSQL is not ready yet..."; \ + sleep 1; \ + done + cat db/scripts/fix_autoincrement_desync.sql | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh; + @for file in db/dev_data/*.sql; do \ + if [ -f "$$file" ]; then \ + echo "Seeding $$file..."; \ + cat $$file | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh; \ + fi \ + done postgres_log: docker logs fortunebet-backend-postgres-1 .PHONY: swagger