fix: disabling all odds market

This commit is contained in:
Samuel Tariku 2025-11-01 23:24:01 +03:00
parent aa893ddf74
commit 8d3127ff53
34 changed files with 2038 additions and 361 deletions

View File

@ -110,7 +110,13 @@ func main() {
v := customvalidator.NewCustomValidator(validator.New()) v := customvalidator.NewCustomValidator(validator.New())
// Initialize services // Initialize services
settingSvc := settings.NewService(repository.NewSettingStore(store)) settingRepo := repository.NewSettingStore(store)
if err := settingRepo.EnsureAllSettingsExist(context.Background()); err != nil {
log.Fatalf("failed to ensure settings: %v", err)
}
settingSvc := settings.NewService(settingRepo)
messengerSvc := messenger.NewService(settingSvc, cfg) messengerSvc := messenger.NewService(settingSvc, cfg)
statSvc := stats.NewService( statSvc := stats.NewService(
repository.NewCompanyStatStore(store), repository.NewCompanyStatStore(store),
@ -142,13 +148,21 @@ func main() {
cfg, cfg,
) )
marketSettingRepo := repository.NewMarketSettingStore(store)
if err := marketSettingRepo.EnsureAllMarketSettingsExist(context.Background()); err != nil {
log.Fatalf("failed to ensure market settings: %v", err)
}
oddsSvc := odds.New( oddsSvc := odds.New(
repository.NewOddStore(store), repository.NewOddStore(store),
marketSettingRepo,
cfg, cfg,
eventSvc, eventSvc,
logger, logger,
domain.MongoDBLogger, domain.MongoDBLogger,
) )
// virtuaGamesRepo := repository.NewVirtualGameRepository(store) // virtuaGamesRepo := repository.NewVirtualGameRepository(store)
// Initialize producer // Initialize producer

View File

@ -81,8 +81,8 @@ VALUES ('sms_provider', 'afro_message'),
('max_unsettled_bets', '100'), ('max_unsettled_bets', '100'),
('bet_amount_limit', '10000000'), ('bet_amount_limit', '10000000'),
('daily_ticket_limit', '50'), ('daily_ticket_limit', '50'),
('total_winnings_limit', '100000000000'), ('total_winnings_limit', '100000000'),
('total_winnings_notify', '100000000'), ('total_winnings_notify', '10000000'),
('amount_for_bet_referral', '1000000'), ('amount_for_bet_referral', '1000000'),
('cashback_amount_cap', '1000'), ('cashback_amount_cap', '1000'),
('default_winning_limit', '5000000'), ('default_winning_limit', '5000000'),

View File

@ -438,6 +438,21 @@ CREATE TABLE company_odd_settings (
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (company_id, odds_market_id) UNIQUE (company_id, odds_market_id)
); );
CREATE TABLE global_odd_market_settings (
market_id BIGINT NOT NULL,
market_name TEXT NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT true,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (market_id)
);
CREATE TABLE company_odd_market_settings (
market_id BIGINT NOT NULL,
market_name TEXT NOT NULL,
company_id BIGINT NOT NULL,
is_active BOOLEAN,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (company_id, market_id)
);
CREATE TABLE result_log ( CREATE TABLE result_log (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
status_not_finished_count INT NOT NULL, status_not_finished_count INT NOT NULL,
@ -750,7 +765,7 @@ FROM customer_wallets cw
LEFT JOIN LATERAL ( LEFT JOIN LATERAL (
SELECT * SELECT *
FROM wallet_stats s FROM wallet_stats s
WHERE s.wallet_id = cw.regular_wallet WHERE s.wallet_id = cw.regular_wallet_id
ORDER BY s.interval_start DESC ORDER BY s.interval_start DESC
LIMIT 1 LIMIT 1
) cs ON true; ) cs ON true;
@ -884,10 +899,12 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id; LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
LEFT JOIN company_odd_market_settings cms ON o.id = cms.market_id;
CREATE VIEW report_request_detail AS CREATE VIEW report_request_detail AS
SELECT r.*, SELECT r.*,
c.name AS company_name, c.name AS company_name,

View File

@ -5,7 +5,7 @@ bet_stats AS (
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(amount), 0) AS total_stake, COALESCE(SUM(amount), 0) AS total_stake,
COALESCE( COALESCE(
SUM(amount) * MAX(companies.deducted_percentage), SUM(amount) * MAX(profit_percent),
0 0
) AS deducted_stake, ) AS deducted_stake,
COALESCE( COALESCE(
@ -71,18 +71,18 @@ SELECT br.id AS branch_id,
c.name AS company_name, c.name AS company_name,
c.slug AS company_slug, c.slug AS company_slug,
DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start, DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start,
COALESCE(b.total_bets, 0) AS total_bets, COALESCE(bs.total_bets, 0) AS total_bets,
COALESCE(b.total_stake, 0) AS total_stake, COALESCE(bs.total_stake, 0) AS total_stake,
COALESCE(b.deducted_stake, 0) AS deducted_stake, COALESCE(bs.deducted_stake, 0) AS deducted_stake,
COALESCE(b.total_cash_out, 0) AS total_cash_out, COALESCE(bs.total_cash_out, 0) AS total_cash_out,
COALESCE(b.total_cash_backs, 0) AS total_cash_backs, COALESCE(bs.total_cash_backs, 0) AS total_cash_backs,
COALESCE(b.number_of_unsettled, 0) AS number_of_unsettled, COALESCE(bs.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(b.total_unsettled_amount, 0) AS total_unsettled_amount, COALESCE(bs.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bc.total_cashiers, 0) AS total_cashiers, COALESCE(bc.total_cashiers, 0) AS total_cashiers,
NOW() AS updated_at NOW() AS updated_at
FROM branches br FROM branches br
LEFT JOIN companies c ON c.id = br.company_id LEFT JOIN companies c ON c.id = br.company_id
LEFT JOIN bet_stats bs ON b.branch_id = br.id LEFT JOIN bet_stats bs ON bs.branch_id = br.id
LEFT JOIN cashier_stats bc ON bc.branch_id = br.id ON CONFLICT (branch_id, interval_start) DO LEFT JOIN cashier_stats bc ON bc.branch_id = br.id ON CONFLICT (branch_id, interval_start) DO
UPDATE UPDATE
SET total_bets = EXCLUDED.total_bets, SET total_bets = EXCLUDED.total_bets,

View File

@ -122,7 +122,7 @@ SET total_bets = EXCLUDED.total_bets,
total_unsettled_amount = EXCLUDED.total_unsettled_amount, total_unsettled_amount = EXCLUDED.total_unsettled_amount,
total_admins = EXCLUDED.total_admins, total_admins = EXCLUDED.total_admins,
total_managers = EXCLUDED.total_managers, total_managers = EXCLUDED.total_managers,
SETtotal_cashiers = EXCLUDED.total_cashiers, total_cashiers = EXCLUDED.total_cashiers,
total_customers = EXCLUDED.total_customers, total_customers = EXCLUDED.total_customers,
total_approvers = EXCLUDED.total_approvers, total_approvers = EXCLUDED.total_approvers,
total_branches = EXCLUDED.total_branches, total_branches = EXCLUDED.total_branches,

View File

@ -83,7 +83,7 @@ SELECT e.*,
FROM events e FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $1 AND ces.company_id = $1
LEFT JOIN event_bet_stats ebs ON ebs.event_id = ewc.id LEFT JOIN event_bet_stats ebs ON ebs.event_id = e.id
JOIN leagues l ON l.id = e.league_id JOIN leagues l ON l.id = e.league_id
LEFT JOIN ( LEFT JOIN (
SELECT event_id, SELECT event_id,
@ -157,9 +157,9 @@ SELECT e.*,
COALESCE(ebs.avg_bet_amount, 0) AS avg_bet_amount, COALESCE(ebs.avg_bet_amount, 0) AS avg_bet_amount,
COALESCE(ebs.total_potential_winnings, 0) AS total_potential_winnings COALESCE(ebs.total_potential_winnings, 0) AS total_potential_winnings
FROM events e FROM events e
LEFT JOIN event_bet_stats ebs ON ebs.event_id = ewc.id
AND ces.company_id = $2
LEFT JOIN company_event_settings ces ON e.id = ces.event_id LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $2
LEFT JOIN event_bet_stats ebs ON ebs.event_id = e.id
JOIN leagues l ON l.id = e.league_id JOIN leagues l ON l.id = e.league_id
LEFT JOIN ( LEFT JOIN (
SELECT event_id, SELECT event_id,

View File

@ -0,0 +1,57 @@
-- name: InsertGlobalMarketSettings :exec
INSERT INTO global_odd_market_settings (market_id, market_name, is_active)
VALUES ($1, $2, $3) ON CONFLICT (market_id) DO
UPDATE
SET is_active = EXCLUDED.is_active,
updated_at = CURRENT_TIMESTAMP;
-- name: InsertCompanyMarketSettings :exec
INSERT INTO company_odd_market_settings (company_id, market_id, market_name, is_active)
VALUES ($1, $2, $3, $4) ON CONFLICT (company_id, market_id) DO
UPDATE
SET is_active = EXCLUDED.is_active,
updated_at = CURRENT_TIMESTAMP;
-- name: GetAllGlobalMarketSettings :many
SELECT *
FROM global_odd_market_settings
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetGlobalMarketSettingsByID :one
SELECT *
FROM global_odd_market_settings
WHERE market_id = $1;
-- name: GetAllCompanyMarketSettings :many
SELECT *
FROM company_odd_market_settings
WHERE (
company_id = sqlc.narg('company_id')
OR sqlc.narg('company_id') IS NULL
)
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetCompanyMarketSettingsByID :one
SELECT *
FROM company_odd_market_settings
WHERE market_id = $1;
-- name: GetAllOverrideMarketSettings :many
SELECT gdm.market_id,
gdm.market_name,
COALESCE(cdm.is_active, gdm.is_active) AS is_active,
COALESCE(cdm.updated_at, gdm.updated_at) AS updated_at
FROM global_odd_market_settings gdm
LEFT JOIN company_odd_market_settings cdm ON cdm.market_id = gdm.market_id
AND company_id = $1
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetOverrideMarketSettingByID :one
SELECT gdm.market_id,
gdm.market_name,
COALESCE(cdm.is_active, gdm.is_active) AS is_active,
COALESCE(cdm.updated_at, gdm.updated_at) AS updated_at
FROM global_odd_market_settings gdm
LEFT JOIN company_odd_market_settings cdm ON cdm.market_id = gdm.market_id
AND company_id = $1
WHERE gdm.market_id = $2;
-- name: DeleteAllMarketSettingsForCompany :exec
DELETE FROM company_odd_market_settings
WHERE company_id = $1;
-- name: DeleteCompanyMarketSettings :exec
DELETE FROM company_odd_market_settings
WHERE market_id = $1
AND company_id = $2;

View File

@ -18,7 +18,7 @@ VALUES (
$5, $5,
$6, $6,
$7, $7,
$8, $8,
$9 $9
) ON CONFLICT (event_id, market_id) DO ) ON CONFLICT (event_id, market_id) DO
UPDATE UPDATE
@ -57,11 +57,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $1 AND cos.company_id = $1
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $1
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetOddByID :one -- name: GetOddByID :one
SELECT * SELECT *
@ -85,12 +88,15 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $3 AND cos.company_id = $3
WHERE market_id = $1 LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $3
WHERE o.market_id = $1
AND event_id = $2; AND event_id = $2;
-- name: GetOddsWithSettingsByID :one -- name: GetOddsWithSettingsByID :one
SELECT o.id, SELECT o.id,
@ -105,11 +111,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $2 AND cos.company_id = $2
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $2
WHERE o.id = $1; WHERE o.id = $1;
-- name: GetOddsByEventID :many -- name: GetOddsByEventID :many
SELECT * SELECT *
@ -141,11 +150,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $2 AND cos.company_id = $2
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $2
WHERE event_id = $1 WHERE event_id = $1
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: DeleteOddsForEvent :exec -- name: DeleteOddsForEvent :exec

View File

@ -1,3 +1,8 @@
-- name: InsertGlobalSetting :exec
INSERT INTO global_settings (key, value)
VALUES ($1, $2) ON CONFLICT (key) DO
UPDATE
SET value = EXCLUDED.value;
-- name: GetGlobalSettings :many -- name: GetGlobalSettings :many
SELECT * SELECT *
FROM global_settings; FROM global_settings;

View File

@ -150,7 +150,7 @@ bet_stats AS (
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(amount), 0) AS total_stake, COALESCE(SUM(amount), 0) AS total_stake,
COALESCE( COALESCE(
SUM(amount) * MAX(companies.deducted_percentage), SUM(amount) * MAX(profit_percent),
0 0
) AS deducted_stake, ) AS deducted_stake,
COALESCE( COALESCE(
@ -216,18 +216,18 @@ SELECT br.id AS branch_id,
c.name AS company_name, c.name AS company_name,
c.slug AS company_slug, c.slug AS company_slug,
DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start, DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start,
COALESCE(b.total_bets, 0) AS total_bets, COALESCE(bs.total_bets, 0) AS total_bets,
COALESCE(b.total_stake, 0) AS total_stake, COALESCE(bs.total_stake, 0) AS total_stake,
COALESCE(b.deducted_stake, 0) AS deducted_stake, COALESCE(bs.deducted_stake, 0) AS deducted_stake,
COALESCE(b.total_cash_out, 0) AS total_cash_out, COALESCE(bs.total_cash_out, 0) AS total_cash_out,
COALESCE(b.total_cash_backs, 0) AS total_cash_backs, COALESCE(bs.total_cash_backs, 0) AS total_cash_backs,
COALESCE(b.number_of_unsettled, 0) AS number_of_unsettled, COALESCE(bs.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(b.total_unsettled_amount, 0) AS total_unsettled_amount, COALESCE(bs.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bc.total_cashiers, 0) AS total_cashiers, COALESCE(bc.total_cashiers, 0) AS total_cashiers,
NOW() AS updated_at NOW() AS updated_at
FROM branches br FROM branches br
LEFT JOIN companies c ON c.id = br.company_id LEFT JOIN companies c ON c.id = br.company_id
LEFT JOIN bet_stats bs ON b.branch_id = br.id LEFT JOIN bet_stats bs ON bs.branch_id = br.id
LEFT JOIN cashier_stats bc ON bc.branch_id = br.id ON CONFLICT (branch_id, interval_start) DO LEFT JOIN cashier_stats bc ON bc.branch_id = br.id ON CONFLICT (branch_id, interval_start) DO
UPDATE UPDATE
SET total_bets = EXCLUDED.total_bets, SET total_bets = EXCLUDED.total_bets,

View File

@ -272,7 +272,7 @@ SET total_bets = EXCLUDED.total_bets,
total_unsettled_amount = EXCLUDED.total_unsettled_amount, total_unsettled_amount = EXCLUDED.total_unsettled_amount,
total_admins = EXCLUDED.total_admins, total_admins = EXCLUDED.total_admins,
total_managers = EXCLUDED.total_managers, total_managers = EXCLUDED.total_managers,
SETtotal_cashiers = EXCLUDED.total_cashiers, total_cashiers = EXCLUDED.total_cashiers,
total_customers = EXCLUDED.total_customers, total_customers = EXCLUDED.total_customers,
total_approvers = EXCLUDED.total_approvers, total_approvers = EXCLUDED.total_approvers,
total_branches = EXCLUDED.total_branches, total_branches = EXCLUDED.total_branches,

View File

@ -28,9 +28,9 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te
COALESCE(ebs.avg_bet_amount, 0) AS avg_bet_amount, COALESCE(ebs.avg_bet_amount, 0) AS avg_bet_amount,
COALESCE(ebs.total_potential_winnings, 0) AS total_potential_winnings COALESCE(ebs.total_potential_winnings, 0) AS total_potential_winnings
FROM events e FROM events e
LEFT JOIN event_bet_stats ebs ON ebs.event_id = ewc.id
AND ces.company_id = $2
LEFT JOIN company_event_settings ces ON e.id = ces.event_id LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $2
LEFT JOIN event_bet_stats ebs ON ebs.event_id = e.id
JOIN leagues l ON l.id = e.league_id JOIN leagues l ON l.id = e.league_id
LEFT JOIN ( LEFT JOIN (
SELECT event_id, SELECT event_id,
@ -153,7 +153,7 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te
FROM events e FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $1 AND ces.company_id = $1
LEFT JOIN event_bet_stats ebs ON ebs.event_id = ewc.id LEFT JOIN event_bet_stats ebs ON ebs.event_id = e.id
JOIN leagues l ON l.id = e.league_id JOIN leagues l ON l.id = e.league_id
LEFT JOIN ( LEFT JOIN (
SELECT event_id, SELECT event_id,

View File

@ -0,0 +1,281 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: market_settings.sql
package dbgen
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const DeleteAllMarketSettingsForCompany = `-- name: DeleteAllMarketSettingsForCompany :exec
DELETE FROM company_odd_market_settings
WHERE company_id = $1
`
func (q *Queries) DeleteAllMarketSettingsForCompany(ctx context.Context, companyID int64) error {
_, err := q.db.Exec(ctx, DeleteAllMarketSettingsForCompany, companyID)
return err
}
const DeleteCompanyMarketSettings = `-- name: DeleteCompanyMarketSettings :exec
DELETE FROM company_odd_market_settings
WHERE market_id = $1
AND company_id = $2
`
type DeleteCompanyMarketSettingsParams struct {
MarketID int64 `json:"market_id"`
CompanyID int64 `json:"company_id"`
}
func (q *Queries) DeleteCompanyMarketSettings(ctx context.Context, arg DeleteCompanyMarketSettingsParams) error {
_, err := q.db.Exec(ctx, DeleteCompanyMarketSettings, arg.MarketID, arg.CompanyID)
return err
}
const GetAllCompanyMarketSettings = `-- name: GetAllCompanyMarketSettings :many
SELECT market_id, market_name, company_id, is_active, updated_at
FROM company_odd_market_settings
WHERE (
company_id = $1
OR $1 IS NULL
)
LIMIT $3 OFFSET $2
`
type GetAllCompanyMarketSettingsParams struct {
CompanyID pgtype.Int8 `json:"company_id"`
Offset pgtype.Int4 `json:"offset"`
Limit pgtype.Int4 `json:"limit"`
}
func (q *Queries) GetAllCompanyMarketSettings(ctx context.Context, arg GetAllCompanyMarketSettingsParams) ([]CompanyOddMarketSetting, error) {
rows, err := q.db.Query(ctx, GetAllCompanyMarketSettings, arg.CompanyID, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CompanyOddMarketSetting
for rows.Next() {
var i CompanyOddMarketSetting
if err := rows.Scan(
&i.MarketID,
&i.MarketName,
&i.CompanyID,
&i.IsActive,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetAllGlobalMarketSettings = `-- name: GetAllGlobalMarketSettings :many
SELECT market_id, market_name, is_active, updated_at
FROM global_odd_market_settings
LIMIT $2 OFFSET $1
`
type GetAllGlobalMarketSettingsParams struct {
Offset pgtype.Int4 `json:"offset"`
Limit pgtype.Int4 `json:"limit"`
}
func (q *Queries) GetAllGlobalMarketSettings(ctx context.Context, arg GetAllGlobalMarketSettingsParams) ([]GlobalOddMarketSetting, error) {
rows, err := q.db.Query(ctx, GetAllGlobalMarketSettings, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GlobalOddMarketSetting
for rows.Next() {
var i GlobalOddMarketSetting
if err := rows.Scan(
&i.MarketID,
&i.MarketName,
&i.IsActive,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetAllOverrideMarketSettings = `-- name: GetAllOverrideMarketSettings :many
SELECT gdm.market_id,
gdm.market_name,
COALESCE(cdm.is_active, gdm.is_active) AS is_active,
COALESCE(cdm.updated_at, gdm.updated_at) AS updated_at
FROM global_odd_market_settings gdm
LEFT JOIN company_odd_market_settings cdm ON cdm.market_id = gdm.market_id
AND company_id = $1
LIMIT $3 OFFSET $2
`
type GetAllOverrideMarketSettingsParams struct {
CompanyID int64 `json:"company_id"`
Offset pgtype.Int4 `json:"offset"`
Limit pgtype.Int4 `json:"limit"`
}
type GetAllOverrideMarketSettingsRow struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetAllOverrideMarketSettings(ctx context.Context, arg GetAllOverrideMarketSettingsParams) ([]GetAllOverrideMarketSettingsRow, error) {
rows, err := q.db.Query(ctx, GetAllOverrideMarketSettings, arg.CompanyID, arg.Offset, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllOverrideMarketSettingsRow
for rows.Next() {
var i GetAllOverrideMarketSettingsRow
if err := rows.Scan(
&i.MarketID,
&i.MarketName,
&i.IsActive,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetCompanyMarketSettingsByID = `-- name: GetCompanyMarketSettingsByID :one
SELECT market_id, market_name, company_id, is_active, updated_at
FROM company_odd_market_settings
WHERE market_id = $1
`
func (q *Queries) GetCompanyMarketSettingsByID(ctx context.Context, marketID int64) (CompanyOddMarketSetting, error) {
row := q.db.QueryRow(ctx, GetCompanyMarketSettingsByID, marketID)
var i CompanyOddMarketSetting
err := row.Scan(
&i.MarketID,
&i.MarketName,
&i.CompanyID,
&i.IsActive,
&i.UpdatedAt,
)
return i, err
}
const GetGlobalMarketSettingsByID = `-- name: GetGlobalMarketSettingsByID :one
SELECT market_id, market_name, is_active, updated_at
FROM global_odd_market_settings
WHERE market_id = $1
`
func (q *Queries) GetGlobalMarketSettingsByID(ctx context.Context, marketID int64) (GlobalOddMarketSetting, error) {
row := q.db.QueryRow(ctx, GetGlobalMarketSettingsByID, marketID)
var i GlobalOddMarketSetting
err := row.Scan(
&i.MarketID,
&i.MarketName,
&i.IsActive,
&i.UpdatedAt,
)
return i, err
}
const GetOverrideMarketSettingByID = `-- name: GetOverrideMarketSettingByID :one
SELECT gdm.market_id,
gdm.market_name,
COALESCE(cdm.is_active, gdm.is_active) AS is_active,
COALESCE(cdm.updated_at, gdm.updated_at) AS updated_at
FROM global_odd_market_settings gdm
LEFT JOIN company_odd_market_settings cdm ON cdm.market_id = gdm.market_id
AND company_id = $1
WHERE gdm.market_id = $2
`
type GetOverrideMarketSettingByIDParams struct {
CompanyID int64 `json:"company_id"`
MarketID int64 `json:"market_id"`
}
type GetOverrideMarketSettingByIDRow struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetOverrideMarketSettingByID(ctx context.Context, arg GetOverrideMarketSettingByIDParams) (GetOverrideMarketSettingByIDRow, error) {
row := q.db.QueryRow(ctx, GetOverrideMarketSettingByID, arg.CompanyID, arg.MarketID)
var i GetOverrideMarketSettingByIDRow
err := row.Scan(
&i.MarketID,
&i.MarketName,
&i.IsActive,
&i.UpdatedAt,
)
return i, err
}
const InsertCompanyMarketSettings = `-- name: InsertCompanyMarketSettings :exec
INSERT INTO company_odd_market_settings (company_id, market_id, market_name, is_active)
VALUES ($1, $2, $3, $4) ON CONFLICT (company_id, market_id) DO
UPDATE
SET is_active = EXCLUDED.is_active,
updated_at = CURRENT_TIMESTAMP
`
type InsertCompanyMarketSettingsParams struct {
CompanyID int64 `json:"company_id"`
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive pgtype.Bool `json:"is_active"`
}
func (q *Queries) InsertCompanyMarketSettings(ctx context.Context, arg InsertCompanyMarketSettingsParams) error {
_, err := q.db.Exec(ctx, InsertCompanyMarketSettings,
arg.CompanyID,
arg.MarketID,
arg.MarketName,
arg.IsActive,
)
return err
}
const InsertGlobalMarketSettings = `-- name: InsertGlobalMarketSettings :exec
INSERT INTO global_odd_market_settings (market_id, market_name, is_active)
VALUES ($1, $2, $3) ON CONFLICT (market_id) DO
UPDATE
SET is_active = EXCLUDED.is_active,
updated_at = CURRENT_TIMESTAMP
`
type InsertGlobalMarketSettingsParams struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
}
func (q *Queries) InsertGlobalMarketSettings(ctx context.Context, arg InsertGlobalMarketSettingsParams) error {
_, err := q.db.Exec(ctx, InsertGlobalMarketSettings, arg.MarketID, arg.MarketName, arg.IsActive)
return err
}

View File

@ -230,6 +230,14 @@ type CompanyLeagueSetting struct {
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
type CompanyOddMarketSetting struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
CompanyID int64 `json:"company_id"`
IsActive pgtype.Bool `json:"is_active"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
type CompanyOddSetting struct { type CompanyOddSetting struct {
ID int64 `json:"id"` ID int64 `json:"id"`
CompanyID int64 `json:"company_id"` CompanyID int64 `json:"company_id"`
@ -518,6 +526,13 @@ type Flag struct {
Resolved pgtype.Bool `json:"resolved"` Resolved pgtype.Bool `json:"resolved"`
} }
type GlobalOddMarketSetting struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
type GlobalSetting struct { type GlobalSetting struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`
@ -625,6 +640,7 @@ type OddsMarketWithSetting struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }

View File

@ -107,11 +107,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $1 AND cos.company_id = $1
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $1
LIMIT $3 OFFSET $2 LIMIT $3 OFFSET $2
` `
@ -134,6 +137,7 @@ type GetAllOddsWithSettingsRow struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
@ -160,6 +164,7 @@ func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWith
&i.ExpiresAt, &i.ExpiresAt,
&i.CompanyID, &i.CompanyID,
&i.IsActive, &i.IsActive,
&i.IsMarketActive,
&i.RawOdds, &i.RawOdds,
&i.UpdatedAt, &i.UpdatedAt,
); err != nil { ); err != nil {
@ -321,11 +326,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $2 AND cos.company_id = $2
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $2
WHERE event_id = $1 WHERE event_id = $1
LIMIT $4 OFFSET $3 LIMIT $4 OFFSET $3
` `
@ -350,6 +358,7 @@ type GetOddsWithSettingsByEventIDRow struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
@ -381,6 +390,7 @@ func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsW
&i.ExpiresAt, &i.ExpiresAt,
&i.CompanyID, &i.CompanyID,
&i.IsActive, &i.IsActive,
&i.IsMarketActive,
&i.RawOdds, &i.RawOdds,
&i.UpdatedAt, &i.UpdatedAt,
); err != nil { ); err != nil {
@ -407,11 +417,14 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $2 AND cos.company_id = $2
LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $2
WHERE o.id = $1 WHERE o.id = $1
` `
@ -433,6 +446,7 @@ type GetOddsWithSettingsByIDRow struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
@ -453,6 +467,7 @@ func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSe
&i.ExpiresAt, &i.ExpiresAt,
&i.CompanyID, &i.CompanyID,
&i.IsActive, &i.IsActive,
&i.IsMarketActive,
&i.RawOdds, &i.RawOdds,
&i.UpdatedAt, &i.UpdatedAt,
) )
@ -472,12 +487,15 @@ SELECT o.id,
o.expires_at, o.expires_at,
cos.company_id, cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_active, COALESCE(cos.is_active, o.default_is_active) AS is_active,
COALESCE(cms.is_active, TRUE) AS is_market_active,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $3 AND cos.company_id = $3
WHERE market_id = $1 LEFT JOIN company_odd_market_settings cms ON o.market_id = cms.market_id
AND cms.company_id = $3
WHERE o.market_id = $1
AND event_id = $2 AND event_id = $2
` `
@ -500,6 +518,7 @@ type GetOddsWithSettingsByMarketIDRow struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
@ -520,6 +539,7 @@ func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOdds
&i.ExpiresAt, &i.ExpiresAt,
&i.CompanyID, &i.CompanyID,
&i.IsActive, &i.IsActive,
&i.IsMarketActive,
&i.RawOdds, &i.RawOdds,
&i.UpdatedAt, &i.UpdatedAt,
) )
@ -546,7 +566,7 @@ VALUES (
$5, $5,
$6, $6,
$7, $7,
$8, $8,
$9 $9
) ON CONFLICT (event_id, market_id) DO ) ON CONFLICT (event_id, market_id) DO
UPDATE UPDATE

View File

@ -240,6 +240,23 @@ func (q *Queries) InsertCompanySetting(ctx context.Context, arg InsertCompanySet
return err return err
} }
const InsertGlobalSetting = `-- name: InsertGlobalSetting :exec
INSERT INTO global_settings (key, value)
VALUES ($1, $2) ON CONFLICT (key) DO
UPDATE
SET value = EXCLUDED.value
`
type InsertGlobalSettingParams struct {
Key string `json:"key"`
Value string `json:"value"`
}
func (q *Queries) InsertGlobalSetting(ctx context.Context, arg InsertGlobalSettingParams) error {
_, err := q.db.Exec(ctx, InsertGlobalSetting, arg.Key, arg.Value)
return err
}
const UpdateGlobalSetting = `-- name: UpdateGlobalSetting :exec const UpdateGlobalSetting = `-- name: UpdateGlobalSetting :exec
UPDATE global_settings UPDATE global_settings
SET value = $2, SET value = $2,

View File

@ -0,0 +1,169 @@
package domain
import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type MarketSettings struct {
MarketID int64
MarketName string
IsActive bool
UpdatedAt time.Time
}
type MarketSettingsRes struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateGlobalMarketSettings struct {
MarketID int64
MarketName string
IsActive bool
}
type CreateCompanyMarketSettings struct {
CompanyID int64
MarketID int64
MarketName string
IsActive ValidBool
}
type CreateCompanyMarketSettingsReq struct {
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive *bool `json:"is_active,omitempty"`
}
type CompanyMarketSettings struct {
CompanyID int64
MarketID int64
MarketName string
IsActive ValidBool
UpdatedAt time.Time
}
type CompanyMarketSettingsRes struct {
CompanyID int64 `json:"company_id"`
MarketID int64 `json:"market_id"`
MarketName string `json:"market_name"`
IsActive bool `json:"is_active"`
UpdatedAt time.Time `json:"updated_at"`
}
type MarketSettingFilter struct {
Limit ValidInt32
Offset ValidInt32
}
type CompanyMarketSettingFilter struct {
Limit ValidInt32
Offset ValidInt32
CompanyID ValidInt64
}
func ConvertMarketSettingsRes(setting MarketSettings) MarketSettingsRes {
return MarketSettingsRes{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive,
UpdatedAt: setting.UpdatedAt,
}
}
func ConvertMarketSettingsResList(settings []MarketSettings) []MarketSettingsRes {
result := make([]MarketSettingsRes, len(settings))
for i, setting := range settings {
result[i] = ConvertMarketSettingsRes(setting)
}
return result
}
func ConvertCreateCompanyMarketSettingsReq(setting CreateCompanyMarketSettingsReq, companyId int64) CreateCompanyMarketSettings {
return CreateCompanyMarketSettings{
CompanyID: companyId,
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: ConvertBoolPtr(setting.IsActive),
}
}
func ConvertCreateGlobalMarketSettings(setting CreateGlobalMarketSettings) dbgen.InsertGlobalMarketSettingsParams {
return dbgen.InsertGlobalMarketSettingsParams{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive,
}
}
func ConvertCreateCompanyMarketSettings(setting CreateCompanyMarketSettings) dbgen.InsertCompanyMarketSettingsParams {
return dbgen.InsertCompanyMarketSettingsParams{
CompanyID: setting.CompanyID,
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive.ToPG(),
}
}
func ConvertDBGlobalMarketSettings(setting dbgen.GlobalOddMarketSetting) MarketSettings {
return MarketSettings{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive,
UpdatedAt: setting.UpdatedAt.Time,
}
}
func ConvertDBCompanyMarketSettingsList(settings []dbgen.CompanyOddMarketSetting) []CompanyMarketSettings {
result := make([]CompanyMarketSettings, len(settings))
for i, setting := range settings {
result[i] = ConvertDBCompanyMarketSettings(setting)
}
return result
}
func ConvertDBCompanyMarketSettings(setting dbgen.CompanyOddMarketSetting) CompanyMarketSettings {
return CompanyMarketSettings{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: ValidBool{
Value: setting.IsActive.Bool,
Valid: setting.IsActive.Valid,
},
UpdatedAt: setting.UpdatedAt.Time,
}
}
func ConvertDBGlobalMarketSettingsList(settings []dbgen.GlobalOddMarketSetting) []MarketSettings {
result := make([]MarketSettings, len(settings))
for i, setting := range settings {
result[i] = ConvertDBGlobalMarketSettings(setting)
}
return result
}
func ConvertDBGetAllOverrideMarketSettings(setting dbgen.GetAllOverrideMarketSettingsRow) MarketSettings {
return MarketSettings{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive,
UpdatedAt: setting.UpdatedAt.Time,
}
}
func ConvertDBGetOverrideMarketSettingsByID(setting dbgen.GetOverrideMarketSettingByIDRow) MarketSettings {
return MarketSettings{
MarketID: setting.MarketID,
MarketName: setting.MarketName,
IsActive: setting.IsActive,
UpdatedAt: setting.UpdatedAt.Time,
}
}
func ConvertDBGetAllOverrideMarketSettingsList(settings []dbgen.GetAllOverrideMarketSettingsRow) []MarketSettings {
result := make([]MarketSettings, len(settings))
for i, setting := range settings {
result[i] = ConvertDBGetAllOverrideMarketSettings(setting)
}
return result
}

File diff suppressed because one or more lines are too long

View File

@ -197,7 +197,7 @@ func ConvertDBOddMarketWithSetting(oms dbgen.OddsMarketWithSetting) (OddMarketWi
RawOdds: rawOdds, RawOdds: rawOdds,
FetchedAt: oms.FetchedAt.Time, FetchedAt: oms.FetchedAt.Time,
ExpiresAt: oms.ExpiresAt.Time, ExpiresAt: oms.ExpiresAt.Time,
IsActive: oms.IsActive, IsActive: oms.IsActive && oms.IsMarketActive,
}, nil }, nil
} }

View File

@ -40,6 +40,63 @@ type SettingList struct {
WelcomeBonusExpire int64 `json:"welcome_bonus_expiry"` WelcomeBonusExpire int64 `json:"welcome_bonus_expiry"`
} }
// Default Global Settings added to the database if the setting isn't found
// This is already configured in the seed_data.sql, but just added it here too
// in case of database to code drift
func NewDefaultSettingList() SettingList {
return SettingList{
SMSProvider: AfroMessage, //Provider that will be used for sending sms
MaxNumberOfOutcomes: 30, //Maximum number of outcomes for a single bet
MaxUnsettledBets: 100, //Maximum number of unsettled bets before system disabled bet service
BetAmountLimit: 10000000, //Maximum amount that can be bet (100,000.00 Birr Limit)
DailyTicketPerIP: 50, //Daily Number of Tickets That can be cut
TotalWinningLimit: 100000000, //Winning Limit (1,000,000.00 Birr)
TotalWinningNotify: 10000000, //Notify if user wins (100,000.00+ Birr)
AmountForBetReferral: 1000000, //Reward for bet referral (only for betting) (10,000.00 Birr)
CashbackAmountCap: 10.00, //Cashback amount limit (10 Birr)
DefaultWinningLimit: 5000000, //Birr Limit on single event (50,000.00)
ReferralRewardAmount: 10000, //Reward for user referral (100.00 Birr)
CashbackPercentage: 0.2, //Cashback Percent (20%)
DefaultMaxReferrals: 15, //Max number of user referrals (15)
MinimumBetAmount: 100, //Minimum Bet Amount (1 Birr)
BetDuplicateLimit: 5, //Maximum number of duplicate bets (5)
SendEmailOnBetFinish: true, //Whether to send email to user when he wins bet
SendSMSOnBetFinish: false, //Whether to send sms to user when he wins bet
WelcomeBonusActive: false, //Is Welcome Bonus in effect
WelcomeBonusMultiplier: 1.5, //Welcome Bonus Multiplier
WelcomeBonusCap: 100000, //Welcome Bonus Limit
WelcomeBonusCount: 3, //Maximum number of welcome bonuses given
WelcomeBonusExpire: 10, //Welcome Bonus Expiry
}
}
func (s SettingList) ToSettingArray() []Setting {
return []Setting{
{"sms_provider", string(s.SMSProvider), time.Now()},
{"max_number_of_outcomes", strconv.FormatInt(s.MaxNumberOfOutcomes, 10), time.Now()},
{"max_unsettled_bets", strconv.FormatInt(s.MaxUnsettledBets, 10), time.Now()},
{"bet_amount_limit", strconv.FormatInt(int64(s.BetAmountLimit), 10), time.Now()},
{"daily_ticket_limit", strconv.FormatInt(s.DailyTicketPerIP, 10), time.Now()},
{"total_winnings_limit", strconv.FormatInt(int64(s.TotalWinningLimit), 10), time.Now()},
{"total_winnings_notify", strconv.FormatInt(int64(s.TotalWinningNotify), 10), time.Now()},
{"amount_for_bet_referral", strconv.FormatInt(int64(s.AmountForBetReferral), 10), time.Now()},
{"cashback_amount_cap", strconv.FormatInt(int64(s.CashbackAmountCap), 10), time.Now()},
{"default_winning_limit", strconv.FormatInt(s.DefaultWinningLimit, 10), time.Now()},
{"referral_reward_amount", strconv.FormatInt(int64(s.ReferralRewardAmount), 10), time.Now()},
{"cashback_percentage", strconv.FormatFloat(float64(s.CashbackPercentage), 'f', -1, 32), time.Now()},
{"default_max_referrals", strconv.FormatInt(s.DefaultMaxReferrals, 10), time.Now()},
{"minimum_bet_amount", strconv.FormatInt(int64(s.MinimumBetAmount), 10), time.Now()},
{"bet_duplicate_limit", strconv.FormatInt(s.BetDuplicateLimit, 10), time.Now()},
{"send_email_on_bet_finish", strconv.FormatBool(s.SendEmailOnBetFinish), time.Now()},
{"send_sms_on_bet_finish", strconv.FormatBool(s.SendSMSOnBetFinish), time.Now()},
{"welcome_bonus_active", strconv.FormatBool(s.WelcomeBonusActive), time.Now()},
{"welcome_bonus_multiplier", strconv.FormatFloat(float64(s.WelcomeBonusMultiplier), 'f', -1, 32), time.Now()},
{"welcome_bonus_cap", strconv.FormatInt(int64(s.WelcomeBonusCap), 10), time.Now()},
{"welcome_bonus_count", strconv.FormatInt(s.WelcomeBonusCount, 10), time.Now()},
{"welcome_bonus_expiry", strconv.FormatInt(s.WelcomeBonusExpire, 10), time.Now()},
}
}
type SettingListRes struct { type SettingListRes struct {
SMSProvider SMSProvider `json:"sms_provider"` SMSProvider SMSProvider `json:"sms_provider"`
MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"` MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"`
@ -596,6 +653,7 @@ func ConvertDBGlobalSettingList(settings []dbgen.GlobalSetting) (SettingList, er
if err := dbSettingList.SetSetting(setting.Key, setting.Value); err != nil { if err := dbSettingList.SetSetting(setting.Key, setting.Value); err != nil {
if err == ErrSettingNotFound { if err == ErrSettingNotFound {
MongoDBLogger.Warn("unknown setting found on database", zap.String("setting", setting.Key)) MongoDBLogger.Warn("unknown setting found on database", zap.String("setting", setting.Key))
continue
} }
MongoDBLogger.Error("unknown error while fetching settings", zap.Error(err)) MongoDBLogger.Error("unknown error while fetching settings", zap.Error(err))
} }

View File

@ -12,6 +12,11 @@ type Setting struct {
UpdatedAt time.Time UpdatedAt time.Time
} }
type CreateSetting struct {
Key string
Value string
}
type SettingRes struct { type SettingRes struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`

View File

@ -1,301 +1,301 @@
//go:generate stringer -type=Market
package domain package domain
type FootballMarket int64 import (
"fmt"
"strings"
)
func GetMarketName(id int64) (string, error) {
name := Market(id).String()
if strings.HasPrefix(name, "Market(") {
return "", fmt.Errorf("prefix_incorrect_%d_name_%v", id, name)
}
name = strings.ToLower(name)
name = strings.ReplaceAll(name, "_", " ")
return name, nil
}
type Market int64
const ( const (
// Main // Main
FOOTBALL_FULL_TIME_RESULT FootballMarket = 40 //"full_time_result" FOOTBALL_FULL_TIME_RESULT Market = 40 //"full_time_result"
FOOTBALL_DOUBLE_CHANCE FootballMarket = 10114 //"double_chance" FOOTBALL_DOUBLE_CHANCE Market = 10114 //"double_chance"
FOOTBALL_GOALS_OVER_UNDER FootballMarket = 981 //"goals_over_under" FOOTBALL_GOALS_OVER_UNDER Market = 981 //"goals_over_under"
FOOTBALL_CORRECT_SCORE FootballMarket = 43 //"correct_score" FOOTBALL_CORRECT_SCORE Market = 43 //"correct_score"
FOOTBALL_ASIAN_HANDICAP FootballMarket = 938 //"asian_handicap" FOOTBALL_ASIAN_HANDICAP Market = 938 //"asian_handicap"
FOOTBALL_GOAL_LINE FootballMarket = 10143 //"goal_line" FOOTBALL_GOAL_LINE Market = 10143 //"goal_line"
// Main New // Main New
FOOTBALL_FULL_TIME_RESULT_ENHANCED FootballMarket = 4001 //"full_time_result__enhanced_prices" FOOTBALL_FULL_TIME_RESULT_ENHANCED Market = 4001 //"full_time_result__enhanced_prices"
FOOTBALL_BOTH_TEAMS_TO_SCORE FootballMarket = 10150 //"both_teams_to_score" FOOTBALL_BOTH_TEAMS_TO_SCORE Market = 10150 //"both_teams_to_score"
FOOTBALL_RESULT_BOTH_TEAMS_TO_SCORE FootballMarket = 50404 //"result_both_teams_to_score" FOOTBALL_RESULT_BOTH_TEAMS_TO_SCORE Market = 50404 //"result_both_teams_to_score"
FOOTBALL_MATCH_GOAL_RANGE FootballMarket = 177816 //"match_goals_range" FOOTBALL_MATCH_GOAL_RANGE Market = 177816 //"match_goals_range"
FOOTBALL_TEAM_GOAL_RANGE FootballMarket = 177817 //"team_goals_range" FOOTBALL_TEAM_GOAL_RANGE Market = 177817 //"team_goals_range"
FOOTBALL_BOTH_TEAMS_TO_RECEIVE_CARDS FootballMarket = 50942 //"both_teams_to_receive_cards" FOOTBALL_BOTH_TEAMS_TO_RECEIVE_CARDS Market = 50942 //"both_teams_to_receive_cards"
FOOTBALL_FIRST_HALF_GOAL_RANGE FootballMarket = 177819 //"1st_half_goals_range" FOOTBALL_FIRST_HALF_GOAL_RANGE Market = 177819 //"1st_half_goals_range"
FOOTBALL_SECOND_HALF_GOAL_RANGE FootballMarket = 177820 //"2nd_half_goals_range" FOOTBALL_SECOND_HALF_GOAL_RANGE Market = 177820 //"2nd_half_goals_range"
FOOTBALL_RESULT_GOAL_RANGE FootballMarket = 177821 //"results_goals_range" FOOTBALL_RESULT_GOAL_RANGE Market = 177821 //"results_goals_range"
FOOTBALL_DOUBLE_CHANCE_GOAL_RANGE FootballMarket = 177822 //"double_chance_goals_range" FOOTBALL_DOUBLE_CHANCE_GOAL_RANGE Market = 177822 //"double_chance_goals_range"
// Half // Half
FOOTBALL_HALF_TIME_RESULT FootballMarket = 1579 //"half_time_result" FOOTBALL_HALF_TIME_RESULT Market = 1579 //"half_time_result"
FOOTBALL_FIRST_HALF_ASIAN_HANDICAP FootballMarket = 50137 //"1st_half_asian_handicap" FOOTBALL_FIRST_HALF_ASIAN_HANDICAP Market = 50137 //"1st_half_asian_handicap"
FOOTBALL_FIRST_HALF_GOAL_LINE FootballMarket = 50136 //"1st_half_goal_line" FOOTBALL_FIRST_HALF_GOAL_LINE Market = 50136 //"1st_half_goal_line"
FOOTBALL_FIRST_TEAM_TO_SCORE FootballMarket = 1178 //"first_team_to_score" FOOTBALL_FIRST_TEAM_TO_SCORE Market = 1178 //"first_team_to_score"
FOOTBALL_GOALS_ODD_EVEN FootballMarket = 10111 //"goals_odd_even" FOOTBALL_GOALS_ODD_EVEN Market = 10111 //"goals_odd_even"
FOOTBALL_DRAW_NO_BET FootballMarket = 10544 //"draw_no_bet" FOOTBALL_DRAW_NO_BET Market = 10544 //"draw_no_bet"
FOOTBALL_HALF_TIME_DOUBLE_CHANCE FootballMarket = 10257 //"half_time_double_chance" FOOTBALL_HALF_TIME_DOUBLE_CHANCE Market = 10257 //"half_time_double_chance"
FOOTBALL_HALF_TIME_RESULT_BOTH_TEAMS_TO_SCORE FootballMarket = 50425 //"half_time_result_both_teams_to_score" FOOTBALL_HALF_TIME_RESULT_BOTH_TEAMS_TO_SCORE Market = 50425 //"half_time_result_both_teams_to_score"
FOOTBALL_ALTERNATE_FIRST_HALF_ASIAN_HANDICAP FootballMarket = 50265 //"alternative_1st_half_asian_handicap" FOOTBALL_ALTERNATE_FIRST_HALF_ASIAN_HANDICAP Market = 50265 //"alternative_1st_half_asian_handicap"
FOOTBALL_ALTERNATE_FIRST_HALF_GOAL_LINE FootballMarket = 50266 //"alternative_1st_half_goal_line" FOOTBALL_ALTERNATE_FIRST_HALF_GOAL_LINE Market = 50266 //"alternative_1st_half_goal_line"
FOOTBALL_FIRST_HALF_HANDICAP FootballMarket = 50264 //"1st_half_handicap" FOOTBALL_FIRST_HALF_HANDICAP Market = 50264 //"1st_half_handicap"
FOOTBALL_ALTERNATE_FIRST_HALF_HANDICAP FootballMarket = 10207 //"alternative_1st_half_handicap_result" FOOTBALL_ALTERNATE_FIRST_HALF_HANDICAP Market = 10207 //"alternative_1st_half_handicap_result"
FOOTBALL_FIRST_HALF_GOAL FootballMarket = 10538 //"first_half_goals" FOOTBALL_FIRST_HALF_GOAL Market = 10538 //"first_half_goals"
FOOTBALL_FIRST_HALF_GOALS_ODD_EVEN FootballMarket = 10206 //"1st_half_goals_odd_even" FOOTBALL_FIRST_HALF_GOALS_ODD_EVEN Market = 10206 //"1st_half_goals_odd_even"
FOOTBALL_SECOND_HALF_GOALS_ODD_EVEN FootballMarket = 50433 //"2nd_half_goals_odd_even" FOOTBALL_SECOND_HALF_GOALS_ODD_EVEN Market = 50433 //"2nd_half_goals_odd_even"
FOOTBALL_HALF_TIME_CORRECT_SCORE FootballMarket = 10540 //"half_time_correct_score" FOOTBALL_HALF_TIME_CORRECT_SCORE Market = 10540 //"half_time_correct_score"
FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF FootballMarket = 50424 //"both_teams_to_score_in_1st_half" FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF Market = 50424 //"both_teams_to_score_in_1st_half"
FOOTBALL_BOTH_TEAMS_TO_SCORE_SECOND_HALF FootballMarket = 50432 //"both_teams_to_score_in_2nd_half" FOOTBALL_BOTH_TEAMS_TO_SCORE_SECOND_HALF Market = 50432 //"both_teams_to_score_in_2nd_half"
FOOTBALL_TO_SCORE_IN_HALF FootballMarket = 50419 //"to_score_in_half" FOOTBALL_TO_SCORE_IN_HALF Market = 50419 //"to_score_in_half"
FOOTBALL_HALF_WITH_MOST_GOALS FootballMarket = 10537 //"half_with_most_goals" FOOTBALL_HALF_WITH_MOST_GOALS Market = 10537 //"half_with_most_goals"
FOOTBALL_HOME_TEAM_WITH_HIGHEST_SCORING_HALF FootballMarket = 50417 //"home_team_highest_scoring_half" FOOTBALL_HOME_TEAM_WITH_HIGHEST_SCORING_HALF Market = 50417 //"home_team_highest_scoring_half"
FOOTBALL_AWAY_TEAM_WITH_HIGHEST_SCORING_HALF FootballMarket = 50418 //"away_team_highest_scoring_half" FOOTBALL_AWAY_TEAM_WITH_HIGHEST_SCORING_HALF Market = 50418 //"away_team_highest_scoring_half"
FOOTBALL_SECOND_HALF_RESULT FootballMarket = 10208 //"2nd_half_result" FOOTBALL_SECOND_HALF_RESULT Market = 10208 //"2nd_half_result"
FOOTBALL_SECOND_HALF_GOALS FootballMarket = 10209 //"2nd_half_goals" FOOTBALL_SECOND_HALF_GOALS Market = 10209 //"2nd_half_goals"
// Minutes // Minutes
FOOTBALL_TEN_MINUTE_RESULT FootballMarket = 10244 //"10_minute_result" FOOTBALL_TEN_MINUTE_RESULT Market = 10244 //"10_minute_result"
FOOTBALL_FIRST_TEN_MINUTE FootballMarket = 10245 //"first_10_minutes_(00:00_09:59)" FOOTBALL_FIRST_TEN_MINUTE Market = 10245 //"first_10_minutes_(00:00_09:59)"
// Others // Others
FOOTBALL_TEAM_PERFORMANCE FootballMarket = 10110 //"team_performances" FOOTBALL_TEAM_PERFORMANCE Market = 10110 //"team_performances"
FOOTBALL_TEAM_TOTAL_GOALS FootballMarket = 10127 //"team_total_goals" FOOTBALL_TEAM_TOTAL_GOALS Market = 10127 //"team_total_goals"
FOOTBALL_ASIAN_TOTAL_CARDS FootballMarket = 10166 //"asian_total_cards" FOOTBALL_ASIAN_TOTAL_CARDS Market = 10166 //"asian_total_cards"
FOOTBALL_EXACT_TOTAL_GOALS FootballMarket = 10203 //"asian_total_cards" FOOTBALL_EXACT_TOTAL_GOALS Market = 10203 //"asian_total_cards"
FOOTBALL_ALTERNATIVE_HANDICAP_RESULT FootballMarket = 10204 //"alternative_handicap_result" FOOTBALL_ALTERNATIVE_HANDICAP_RESULT Market = 10204 //"alternative_handicap_result"
FOOTBALL_EXACT_FIRST_HALF_GOALS FootballMarket = 10205 //"exact_1st_half_goals" FOOTBALL_EXACT_FIRST_HALF_GOALS Market = 10205 //"exact_1st_half_goals"
FOOTBALL_CLEAN_SHEET FootballMarket = 10210 //"clean_sheet" FOOTBALL_CLEAN_SHEET Market = 10210 //"clean_sheet"
FOOTBALL_TEAMS_TO_SCORE FootballMarket = 10211 //"teams_to_score" FOOTBALL_TEAMS_TO_SCORE Market = 10211 //"teams_to_score"
FOOTBALL_TIME_OF_FIRST_TEAM_GOAL FootballMarket = 10214 //"time_of_1st_team_goal" FOOTBALL_TIME_OF_FIRST_TEAM_GOAL Market = 10214 //"time_of_1st_team_goal"
FOOTBALL_FIRST_GOAL_METHOD FootballMarket = 10216 //"first_goal_method" FOOTBALL_FIRST_GOAL_METHOD Market = 10216 //"first_goal_method"
FOOTBALL_MULTI_SCORERS FootballMarket = 10217 //"multi_scorers" FOOTBALL_MULTI_SCORERS Market = 10217 //"multi_scorers"
FOOTBALL_OWN_GOAL FootballMarket = 10223 //"own_goal" FOOTBALL_OWN_GOAL Market = 10223 //"own_goal"
FOOTBALL_TO_SCORE_PENALTY FootballMarket = 10229 //"to_score_a_penalty" FOOTBALL_TO_SCORE_PENALTY Market = 10229 //"to_score_a_penalty"
FOOTBALL_TO_MISS_PENALTY FootballMarket = 10230 //"to_miss_a_penalty" FOOTBALL_TO_MISS_PENALTY Market = 10230 //"to_miss_a_penalty"
FOOTBALL_ASIAN_HANDICAP_CARDS FootballMarket = 10239 //"asian_handicap_cards" FOOTBALL_ASIAN_HANDICAP_CARDS Market = 10239 //"asian_handicap_cards"
FOOTBALL_CARD_HANDICAP FootballMarket = 10240 //"card_handicap" FOOTBALL_CARD_HANDICAP Market = 10240 //"card_handicap"
FOOTBALL_ALTERNATIVE_CARD_HANDICAP FootballMarket = 10241 //"alternative_card_handicap" FOOTBALL_ALTERNATIVE_CARD_HANDICAP Market = 10241 //"alternative_card_handicap"
FOOTBALL_TEAM_CARDS FootballMarket = 10242 //"team_cards" FOOTBALL_TEAM_CARDS Market = 10242 //"team_cards"
FOOTBALL_EXACT_SECOND_HALF_GOALS FootballMarket = 10252 //"exact_2nd_half_goals" FOOTBALL_EXACT_SECOND_HALF_GOALS Market = 10252 //"exact_2nd_half_goals"
FOOTBALL_EARLY_GOAL FootballMarket = 10258 //"early_goal" FOOTBALL_EARLY_GOAL Market = 10258 //"early_goal"
FOOTBALL_LATE_GOAL FootballMarket = 10259 //"late_goal" FOOTBALL_LATE_GOAL Market = 10259 //"late_goal"
FOOTBALL_FIRST_MATCH_CORNER FootballMarket = 10519 //"first_match_corner" FOOTBALL_FIRST_MATCH_CORNER Market = 10519 //"first_match_corner"
FOOTBALL_LAST_MATCH_CORNER FootballMarket = 10520 //"last_match_corner" FOOTBALL_LAST_MATCH_CORNER Market = 10520 //"last_match_corner"
FOOTBALL_LAST_TEAM_TO_SCORE FootballMarket = 10534 //"last_team_to_score" FOOTBALL_LAST_TEAM_TO_SCORE Market = 10534 //"last_team_to_score"
FOOTBALL_CORNER_HANDICAP FootballMarket = 10535 //"corner_handicap" FOOTBALL_CORNER_HANDICAP Market = 10535 //"corner_handicap"
FOOTBALL_NUMBER_OF_GOALS_IN_MATCH FootballMarket = 10536 //"number_of_goals_in_match" FOOTBALL_NUMBER_OF_GOALS_IN_MATCH Market = 10536 //"number_of_goals_in_match"
FOOTBALL_TIME_OF_FIRST_GOAL_BRACKETS FootballMarket = 10541 //"time_of_first_goal_brackets" FOOTBALL_TIME_OF_FIRST_GOAL_BRACKETS Market = 10541 //"time_of_first_goal_brackets"
FOOTBALL_CORNER_MATCH_BET FootballMarket = 1175 //"corner_match_bet" FOOTBALL_CORNER_MATCH_BET Market = 1175 //"corner_match_bet"
FOOTBALL_MULTI_CORNERS FootballMarket = 1181 //"Multicorners" FOOTBALL_MULTI_CORNERS Market = 1181 //"Multicorners"
FOOTBALL_TIME_OF_FIRST_CARD FootballMarket = 1183 //"time_of_first_card" FOOTBALL_TIME_OF_FIRST_CARD Market = 1183 //"time_of_first_card"
FOOTBALL_HANDICAP_RESULT FootballMarket = 171 //"handicap_result" FOOTBALL_HANDICAP_RESULT Market = 171 //"handicap_result"
FOOTBALL_TOTAL_GOAL_MINUTES FootballMarket = 1776 //"total_goal_minutes" FOOTBALL_TOTAL_GOAL_MINUTES Market = 1776 //"total_goal_minutes"
FOOTBALL_PLAYER_TO_SCORE_ASSIST FootballMarket = 177704 //"player_to_score_or_assist" FOOTBALL_PLAYER_TO_SCORE_ASSIST Market = 177704 //"player_to_score_or_assist"
FOOTBALL_TEAM_TO_GET_MOST FootballMarket = 177790 //"team_to_get_most" FOOTBALL_TEAM_TO_GET_MOST Market = 177790 //"team_to_get_most"
FOOTBALL_GOALSCORER FootballMarket = 45 //"goalscorers" FOOTBALL_GOALSCORER Market = 45 //"goalscorers"
FOOTBALL_FIRST_CARD_RECEIVED FootballMarket = 476 //"first_card_received" FOOTBALL_FIRST_CARD_RECEIVED Market = 476 //"first_card_received"
FOOTBALL_PLAYER_CARD FootballMarket = 50135 //"player_cards" FOOTBALL_PLAYER_CARD Market = 50135 //"player_cards"
FOOTBALL_ALTERNATIVE_ASIAN_HANDICAP FootballMarket = 50138 //"alternative_asian_handicap" FOOTBALL_ALTERNATIVE_ASIAN_HANDICAP Market = 50138 //"alternative_asian_handicap"
FOOTBALL_ALTERNATIVE_GOAL_LINE FootballMarket = 50139 //"alternative_goal_line" FOOTBALL_ALTERNATIVE_GOAL_LINE Market = 50139 //"alternative_goal_line"
FOOTBALL_HOME_TEAM_ODD_EVEN_GOALS FootballMarket = 50406 //"home_team_odd_even_goals" FOOTBALL_HOME_TEAM_ODD_EVEN_GOALS Market = 50406 //"home_team_odd_even_goals"
FOOTBALL_AWAY_TEAM_ODD_EVEN_GOALS FootballMarket = 50407 //"away_team_odd_even_goals" FOOTBALL_AWAY_TEAM_ODD_EVEN_GOALS Market = 50407 //"away_team_odd_even_goals"
FOOTBALL_HOME_TEAM_EXACT_GOALS FootballMarket = 50415 //"home_team_exact_goals" FOOTBALL_HOME_TEAM_EXACT_GOALS Market = 50415 //"home_team_exact_goals"
FOOTBALL_AWAY_TEAM_EXACT_GOALS FootballMarket = 50416 //"away_team_exact_goals" FOOTBALL_AWAY_TEAM_EXACT_GOALS Market = 50416 //"away_team_exact_goals"
FOOTBALL_HALF_TIME_RESULT_TOTAL_GOALS FootballMarket = 50426 //"half_time_result_total_goals" FOOTBALL_HALF_TIME_RESULT_TOTAL_GOALS Market = 50426 //"half_time_result_total_goals"
FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF_SECOND_HALF FootballMarket = 50435 //"both_teams_to_score_1st_half_2nd_half" FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF_SECOND_HALF Market = 50435 //"both_teams_to_score_1st_half_2nd_half"
FOOTBALL_MATCH_SHOTS_ON_TARGET FootballMarket = 50527 //"match_shots_on_target" FOOTBALL_MATCH_SHOTS_ON_TARGET Market = 50527 //"match_shots_on_target"
FOOTBALL_MATCH_SHOTS FootballMarket = 50528 //"match_shots" FOOTBALL_MATCH_SHOTS Market = 50528 //"match_shots"
FOOTBALL_TEAM_SHOTS_ON_TARGET FootballMarket = 50530 //"team_shots_on_target" FOOTBALL_TEAM_SHOTS_ON_TARGET Market = 50530 //"team_shots_on_target"
FOOTBALL_TEAM_SHOTS FootballMarket = 50532 //"team_shots" FOOTBALL_TEAM_SHOTS Market = 50532 //"team_shots"
FOOTBALL_GOAL_METHOD FootballMarket = 50962 //"goal_method" FOOTBALL_GOAL_METHOD Market = 50962 //"goal_method"
FOOTBALL_WINNING_MARGIN FootballMarket = 56 //"winning_margin" FOOTBALL_WINNING_MARGIN Market = 56 //"winning_margin"
FOOTBALL_TIME_OF_FIRST_CORNER FootballMarket = 761 //"time_of_first_corner" FOOTBALL_TIME_OF_FIRST_CORNER Market = 761 //"time_of_first_corner"
// Player // Player
FOOTBALL_TEAM_GOALSCORER FootballMarket = 10151 //"team_goalscorer" FOOTBALL_TEAM_GOALSCORER Market = 10151 //"team_goalscorer"
FOOTBALL_PLAYER_SHOTS_ON_TARGET FootballMarket = 50920 //"player_shots_on_target" FOOTBALL_PLAYER_SHOTS_ON_TARGET Market = 50920 //"player_shots_on_target"
FOOTBALL_PLAYER_SHOTS FootballMarket = 50921 //"player_shots" FOOTBALL_PLAYER_SHOTS Market = 50921 //"player_shots"
// Specials // Specials
FOOTBALL_SPECIALS FootballMarket = 10224 //"specials FOOTBALL_SPECIALS Market = 10224 //"specials
// Corner // Corner
FOOTBALL_CORNERS FootballMarket = 760 //"corners" FOOTBALL_CORNERS Market = 760 //"corners"
FOOTBALL_CORNERS_TWO_WAY FootballMarket = 10235 //"corners_2_way" FOOTBALL_CORNERS_TWO_WAY Market = 10235 //"corners_2_way"
FOOTBALL_FIRST_HALF_CORNERS FootballMarket = 10539 //"first_half_corners" FOOTBALL_FIRST_HALF_CORNERS Market = 10539 //"first_half_corners"
FOOTBALL_ASIAN_TOTAL_CORNERS FootballMarket = 10164 //"asian_total_corners" FOOTBALL_ASIAN_TOTAL_CORNERS Market = 10164 //"asian_total_corners"
FOOTBALL_FIRST_HALF_ASIAN_CORNERS FootballMarket = 10233 //"1st_half_asian_corners" FOOTBALL_FIRST_HALF_ASIAN_CORNERS Market = 10233 //"1st_half_asian_corners"
FOOTBALL_ASIAN_HANDICAP_CORNERS FootballMarket = 10165 //"asian_handicap_corners" FOOTBALL_ASIAN_HANDICAP_CORNERS Market = 10165 //"asian_handicap_corners"
FOOTBALL_ALTERNATIVE_CORNER FootballMarket = 10234 //"alternative_corners" FOOTBALL_ALTERNATIVE_CORNER Market = 10234 //"alternative_corners"
FOOTBALL_CORNER_RACE FootballMarket = 10238 //"corners_race" FOOTBALL_CORNER_RACE Market = 10238 //"corners_race"
// Cards // Cards
FOOTBALL_NUMBER_OF_CARDS_IN_MATCH FootballMarket = 10542 //"number_of_cards_in_match" FOOTBALL_NUMBER_OF_CARDS_IN_MATCH Market = 10542 //"number_of_cards_in_match"
) )
type BasketBallMarket int64 // Basketball Markets
const ( const (
// Main // Main
BASKETBALL_GAME_LINES BasketBallMarket = 1453 //"game_lines" BASKETBALL_GAME_LINES Market = 1453 //"game_lines"
BASKETBALL_FIRST_HALF BasketBallMarket = 928 //"1st_half" BASKETBALL_FIRST_HALF Market = 928 //"1st_half"
BASKETBALL_FIRST_QUARTER BasketBallMarket = 941 //"1st_quarter" BASKETBALL_FIRST_QUARTER Market = 941 //"1st_quarter"
// Main Props // Main Props
BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS BasketBallMarket = 181273 //"result_and_both_teams_to_score_'x'_points" BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS Market = 181273 //"result_and_both_teams_to_score_'x'_points"
BASKETBALL_DOUBLE_RESULT BasketBallMarket = 1517 //"double_result" BASKETBALL_DOUBLE_RESULT Market = 1517 //"double_result"
BASKETBALL_MATCH_RESULT_AND_TOTAL BasketBallMarket = 181125 //"match_result_and_total" BASKETBALL_MATCH_RESULT_AND_TOTAL Market = 181125 //"match_result_and_total"
BASKETBALL_MATCH_HANDICAP_AND_TOTAL BasketBallMarket = 181126 //"match_handicap_and_total" BASKETBALL_MATCH_HANDICAP_AND_TOTAL Market = 181126 //"match_handicap_and_total"
BASKETBALL_RACE_TO_20_POINTS BasketBallMarket = 1503 //"race_to_20_points" BASKETBALL_RACE_TO_20_POINTS Market = 1503 //"race_to_20_points"
BASKETBALL_TIED_AT_END_OF_REGULATION BasketBallMarket = 181127 //"tied_at_end_of_regulation" BASKETBALL_TIED_AT_END_OF_REGULATION Market = 181127 //"tied_at_end_of_regulation"
BASKETBALL_QUARTER_CORRECT_SCORE BasketBallMarket = 181276 //"quarter_correct_score" BASKETBALL_QUARTER_CORRECT_SCORE Market = 181276 //"quarter_correct_score"
// Half Props // Half Props
BASKETBALL_FIRST_HALF_TEAM_TOTALS BasketBallMarket = 181159 //"1st_half_team_totals" BASKETBALL_FIRST_HALF_TEAM_TOTALS Market = 181159 //"1st_half_team_totals"
BASKETBALL_FIRST_HALF_WINNING_MARGIN BasketBallMarket = 181185 //"1st_half_winning_margin" BASKETBALL_FIRST_HALF_WINNING_MARGIN Market = 181185 //"1st_half_winning_margin"
BASKETBALL_FIRST_HALF_RESULT_AND_TOTAL BasketBallMarket = 181181 //"1st_half_result_and_total" BASKETBALL_FIRST_HALF_RESULT_AND_TOTAL Market = 181181 //"1st_half_result_and_total"
BASKETBALL_FIRST_HALF_HANDICAP_AND_TOTAL BasketBallMarket = 181182 //"1st_half_handicap_and_total" BASKETBALL_FIRST_HALF_HANDICAP_AND_TOTAL Market = 181182 //"1st_half_handicap_and_total"
BASKETBALL_FIRST_HALF_RACE_TO_POINTS BasketBallMarket = 181186 //"1st_half_race_to_(points)" BASKETBALL_FIRST_HALF_RACE_TO_POINTS Market = 181186 //"1st_half_race_to_(points)"
BASKETBALL_FIRST_HALF_BOTH_TEAMS_TO_SCORE_X_POINTS BasketBallMarket = 181195 //"1st_half_both_teams_to_score_x_points" BASKETBALL_FIRST_HALF_BOTH_TEAMS_TO_SCORE_X_POINTS Market = 181195 //"1st_half_both_teams_to_score_x_points"
BASKETBALL_FIRST_HALF_TEAM_TO_SCORE_X_POINTS BasketBallMarket = 181198 //"1st_half_team_to_score_x_points" BASKETBALL_FIRST_HALF_TEAM_TO_SCORE_X_POINTS Market = 181198 //"1st_half_team_to_score_x_points"
BASKETBALL_FIRST_HALF_MONEY_LINE_3_WAY BasketBallMarket = 181183 //"1st_half_money_line_3_way" BASKETBALL_FIRST_HALF_MONEY_LINE_3_WAY Market = 181183 //"1st_half_money_line_3_way"
// Others // Others
BASKETBALL_GAME_TOTAL_ODD_EVEN BasketBallMarket = 180013 //"game_total_odd_even" BASKETBALL_GAME_TOTAL_ODD_EVEN Market = 180013 //"game_total_odd_even"
BASKETBALL_FIRST_QUARTER_TOTAL_ODD_EVEN BasketBallMarket = 180170 //"1st_quarter_total_odd_even" BASKETBALL_FIRST_QUARTER_TOTAL_ODD_EVEN Market = 180170 //"1st_quarter_total_odd_even"
BASKETBALL_FIRST_QUARTER_MARGIN_OF_VICTORY BasketBallMarket = 180180 //"1st_quarter_margin_of_victory" BASKETBALL_FIRST_QUARTER_MARGIN_OF_VICTORY Market = 180180 //"1st_quarter_margin_of_victory"
BASKETBALL_HIGHEST_SCORING_HALF BasketBallMarket = 181131 //"highest_scoring_half" BASKETBALL_HIGHEST_SCORING_HALF Market = 181131 //"highest_scoring_half"
BASKETBALL_HIGHEST_SCORING_QUARTER BasketBallMarket = 181132 //"highest_scoring_quarter" BASKETBALL_HIGHEST_SCORING_QUARTER Market = 181132 //"highest_scoring_quarter"
BASKETBALL_FIRST_HALF_DOUBLE_CHANCE BasketBallMarket = 181184 //"1st_half_double_chance" BASKETBALL_FIRST_HALF_DOUBLE_CHANCE Market = 181184 //"1st_half_double_chance"
BASKETBALL_FIRST_HALF_TOTAL_ODD_EVEN BasketBallMarket = 181204 //"1st_half_total_odd_even" BASKETBALL_FIRST_HALF_TOTAL_ODD_EVEN Market = 181204 //"1st_half_total_odd_even"
BASKETBALL_FIRST_QUARTER_3_WAY_LINES BasketBallMarket = 181212 //"1st_quarter_3_way_lines" BASKETBALL_FIRST_QUARTER_3_WAY_LINES Market = 181212 //"1st_quarter_3_way_lines"
BASKETBALL_FIRST_QUARTER_RESULT_AND_TOTAL BasketBallMarket = 181242 //"1st_quarter_result_and_total" BASKETBALL_FIRST_QUARTER_RESULT_AND_TOTAL Market = 181242 //"1st_quarter_result_and_total"
BASKETBALL_FIRST_QUARTER_HANDICAP_AND_TOTAL BasketBallMarket = 181243 //"1st_quarter_handicap_and_total" BASKETBALL_FIRST_QUARTER_HANDICAP_AND_TOTAL Market = 181243 //"1st_quarter_handicap_and_total"
BASKETBALL_FIRST_QUARTER_DOUBLE_CHANCE BasketBallMarket = 181245 //"1st_quarter_double_chance" BASKETBALL_FIRST_QUARTER_DOUBLE_CHANCE Market = 181245 //"1st_quarter_double_chance"
BASKETBALL_FIRST_QUARTER_RACE_TO_POINTS BasketBallMarket = 181248 //"1st_quarter_race_to_(points)" BASKETBALL_FIRST_QUARTER_RACE_TO_POINTS Market = 181248 //"1st_quarter_race_to_(points)"
BASKETBALL_FIRST_QUARTER_BOTH_TEAMS_TO_SCORE_X_POINTS BasketBallMarket = 181252 //"1st_quarter_both_teams_to_score_x_points" BASKETBALL_FIRST_QUARTER_BOTH_TEAMS_TO_SCORE_X_POINTS Market = 181252 //"1st_quarter_both_teams_to_score_x_points"
BASKETBALL_FIRST_QUARTER_TEAM_TO_SCORE_X_POINTS BasketBallMarket = 181255 //"1st_quarter_team_to_score_x_points" BASKETBALL_FIRST_QUARTER_TEAM_TO_SCORE_X_POINTS Market = 181255 //"1st_quarter_team_to_score_x_points"
// Quarter Props // Quarter Props
BASKETBALL_FIRST_QUARTER_TEAM_TOTALS BasketBallMarket = 181220 //"1st_quarter_team_totals" BASKETBALL_FIRST_QUARTER_TEAM_TOTALS Market = 181220 //"1st_quarter_team_totals"
BASKETBALL_FIRST_QUARTER_WINNING_MARGIN BasketBallMarket = 181247 //"1st_quarter_winning_margin" BASKETBALL_FIRST_QUARTER_WINNING_MARGIN Market = 181247 //"1st_quarter_winning_margin"
// Team Props // Team Props
BASKETBALL_TEAM_WITH_HIGHEST_SCORING_QUARTER BasketBallMarket = 181377 //"team_with_highest_scoring_quarter" BASKETBALL_TEAM_WITH_HIGHEST_SCORING_QUARTER Market = 181377 //"team_with_highest_scoring_quarter"
BASKETBALL_TEAM_TOTALS BasketBallMarket = 181335 //"team_totals" BASKETBALL_TEAM_TOTALS Market = 181335 //"team_totals"
BASKETBALL_TEAM_TOTAL_ODD_EVEN BasketBallMarket = 1731 //"team_total_odd_even" BASKETBALL_TEAM_TOTAL_ODD_EVEN Market = 1731 //"team_total_odd_even"
) )
type IceHockeyMarket int64
const ( const (
// Main // Main
ICE_HOCKEY_GAME_LINES IceHockeyMarket = 972 ICE_HOCKEY_GAME_LINES Market = 972
ICE_HOCKEY_FIRST_PERIOD IceHockeyMarket = 1531 ICE_HOCKEY_FIRST_PERIOD Market = 1531
ICE_HOCKEY_THREE_WAY IceHockeyMarket = 170008 ICE_HOCKEY_THREE_WAY Market = 170008
ICE_HOCKEY_DRAW_NO_BET IceHockeyMarket = 170447 ICE_HOCKEY_DRAW_NO_BET Market = 170447
ICE_HOCKEY_DOUBLE_CHANCE IceHockeyMarket = 170038 ICE_HOCKEY_DOUBLE_CHANCE Market = 170038
ICE_HOCKEY_WINNING_MARGIN IceHockeyMarket = 1556 ICE_HOCKEY_WINNING_MARGIN Market = 1556
ICE_HOCKEY_HIGHEST_SCORING_PERIOD IceHockeyMarket = 1557 ICE_HOCKEY_HIGHEST_SCORING_PERIOD Market = 1557
ICE_HOCKEY_TIED_AFTER_REGULATION IceHockeyMarket = 170479 ICE_HOCKEY_TIED_AFTER_REGULATION Market = 170479
ICE_HOCKEY_WHEN_WILL_MATCH_END IceHockeyMarket = 170481 ICE_HOCKEY_WHEN_WILL_MATCH_END Market = 170481
ICE_HOCKEY_GAME_TOTAL_ODD_EVEN IceHockeyMarket = 170013 ICE_HOCKEY_GAME_TOTAL_ODD_EVEN Market = 170013
ICE_HOCKEY_ALTERNATIVE_PUCK_LINE_TWO_WAY IceHockeyMarket = 170226 ICE_HOCKEY_ALTERNATIVE_PUCK_LINE_TWO_WAY Market = 170226
ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY IceHockeyMarket = 170240 ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY Market = 170240
) )
type CricketMarket int64
const ( const (
// Main // Main
CRICKET_TO_WIN_THE_MATCH CricketMarket = 1246 CRICKET_TO_WIN_THE_MATCH Market = 1246
CRICKET_TEAM_TOP_BATTER CricketMarket = 1241 CRICKET_TEAM_TOP_BATTER Market = 1241
CRICKET_TEAM_TOP_BOWLE CricketMarket = 1242 CRICKET_TEAM_TOP_BOWLE Market = 1242
CRICKET_PLAYER_OF_THE_MATCH CricketMarket = 346 CRICKET_PLAYER_OF_THE_MATCH Market = 346
CRICKET_FIRST_WICKET_METHOD CricketMarket = 30205 CRICKET_FIRST_WICKET_METHOD Market = 30205
// First Over // First Over
CRICKET_FIRST_OVER_TOTAL_RUNS CricketMarket = 300336 CRICKET_FIRST_OVER_TOTAL_RUNS Market = 300336
CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even CricketMarket = 300118 CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even Market = 300118
// Inninigs 1 // Inninigs 1
CRICKET_FIRST_INNINIGS_SCORE CricketMarket = 300338 CRICKET_FIRST_INNINIGS_SCORE Market = 300338
CRICKET_INNINGS_OF_MATCH_BOWLED_OUT CricketMarket = 300108 CRICKET_INNINGS_OF_MATCH_BOWLED_OUT Market = 300108
// Match // Match
CRICKET_TOP_MATCH_BATTER CricketMarket = 30245 CRICKET_TOP_MATCH_BATTER Market = 30245
CRICKET_TOP_MATCH_BOWLER CricketMarket = 30246 CRICKET_TOP_MATCH_BOWLER Market = 30246
) )
type VolleyballMarket int64
const ( const (
VOLLEYBALL_GAME_LINES VolleyballMarket = 910000 VOLLEYBALL_GAME_LINES Market = 910000
VOLLEYBALL_CORRECT_SET_SCORE VolleyballMarket = 910201 VOLLEYBALL_CORRECT_SET_SCORE Market = 910201
VOLLEYBALL_MATCH_TOTAL_ODD_EVEN VolleyballMarket = 910217 VOLLEYBALL_MATCH_TOTAL_ODD_EVEN Market = 910217
VOLLEYBALL_SET_ONE_LINES VolleyballMarket = 910204 VOLLEYBALL_SET_ONE_LINES Market = 910204
VOLLEYBALL_SET_ONE_TO_GO_TO_EXTRA_POINTS VolleyballMarket = 910209 VOLLEYBALL_SET_ONE_TO_GO_TO_EXTRA_POINTS Market = 910209
VOLLEYBALL_SET_ONE_TOTAL_ODD_EVEN VolleyballMarket = 910218 VOLLEYBALL_SET_ONE_TOTAL_ODD_EVEN Market = 910218
) )
type DartsMarket int64
const ( const (
// Main // Main
DARTS_MATCH_WINNER DartsMarket = 703 // match_winner DARTS_MATCH_WINNER Market = 703 // match_winner
DARTS_MATCH_DOUBLE DartsMarket = 150228 // match_double DARTS_MATCH_DOUBLE Market = 150228 // match_double
DARTS_MATCH_TREBLE DartsMarket = 150230 // match_treble DARTS_MATCH_TREBLE Market = 150230 // match_treble
DARTS_CORRECT_LEG_SCORE DartsMarket = 150015 // correct_leg_score DARTS_CORRECT_LEG_SCORE Market = 150015 // correct_leg_score
DARTS_TOTAL_LEGS DartsMarket = 150117 // total_legs DARTS_TOTAL_LEGS Market = 150117 // total_legs
DARTS_MOST_HUNDERED_EIGHTYS DartsMarket = 150030 // "most_180s" DARTS_MOST_HUNDERED_EIGHTYS Market = 150030 // "most_180s"
DARTS_TOTAL_HUNDERED_EIGHTYS DartsMarket = 150012 // total_180s DARTS_TOTAL_HUNDERED_EIGHTYS Market = 150012 // total_180s
DARTS_MOST_HUNDERED_EIGHTYS_HANDICAP DartsMarket = 150227 // most_180s_handicap DARTS_MOST_HUNDERED_EIGHTYS_HANDICAP Market = 150227 // most_180s_handicap
DARTS_PLAYER_HUNDERED_EIGHTYS DartsMarket = 150121 // player_180s DARTS_PLAYER_HUNDERED_EIGHTYS Market = 150121 // player_180s
DARTS_FIRST_DART DartsMarket = 150125 // first_dart DARTS_FIRST_DART Market = 150125 // first_dart
) )
type FutsalMarket int64
const ( const (
// Main // Main
FUTSAL_GAME_LINES FutsalMarket = 830001 FUTSAL_GAME_LINES Market = 830001
FUTSAL_MONEY_LINE FutsalMarket = 830130 FUTSAL_MONEY_LINE Market = 830130
// Others // Others
FUTSAL_DOUBLE_RESULT_9_WAY FutsalMarket = 830124 FUTSAL_DOUBLE_RESULT_9_WAY Market = 830124
// Score // Score
FUTSAL_TEAM_TO_SCORE_FIRST FutsalMarket = 830141 FUTSAL_TEAM_TO_SCORE_FIRST Market = 830141
FUTSAL_RACE_TO_GOALS FutsalMarket = 830142 FUTSAL_RACE_TO_GOALS Market = 830142
) )
type AmericanFootballMarket int64
const ( const (
// Main // Main
AMERICAN_FOOTBALL_GAME_LINES AmericanFootballMarket = 1441 AMERICAN_FOOTBALL_GAME_LINES Market = 1441
) )
type RugbyLeagueMarket int64
const ( const (
// Main // Main
RUGBY_L_GAME_BETTING_2_WAY RugbyLeagueMarket = 190006 RUGBY_L_GAME_BETTING_2_WAY Market = 190006
) )
type RugbyUnionMarket int64
const ( const (
// Main // Main
RUGBY_U_GAME_BETTING_2_WAY RugbyLeagueMarket = 80007 RUGBY_U_GAME_BETTING_2_WAY Market = 80007
) )
type BaseballMarket int64
const ( const (
// Main // Main
BASEBALL_GAME_LINES BaseballMarket = 1096 BASEBALL_GAME_LINES Market = 1096
) )
// TODO: Move this into the database so that it can be modified dynamically // TODO: Move this into the database so that it can be modified dynamically
@ -323,6 +323,48 @@ var SupportedMarkets = map[int64]bool{
int64(FOOTBALL_FIRST_HALF_GOALS_ODD_EVEN): true, int64(FOOTBALL_FIRST_HALF_GOALS_ODD_EVEN): true,
int64(FOOTBALL_SECOND_HALF_GOALS_ODD_EVEN): true, int64(FOOTBALL_SECOND_HALF_GOALS_ODD_EVEN): true,
int64(FOOTBALL_FULL_TIME_RESULT_ENHANCED): true,
int64(FOOTBALL_ALTERNATIVE_ASIAN_HANDICAP): true,
int64(FOOTBALL_ALTERNATIVE_GOAL_LINE): true,
int64(FOOTBALL_ALTERNATE_FIRST_HALF_ASIAN_HANDICAP): true,
int64(FOOTBALL_ALTERNATE_FIRST_HALF_GOAL_LINE): true,
int64(FOOTBALL_ALTERNATIVE_CORNER): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_RESULT_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_HALF_TIME_CORRECT_SCORE): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE_SECOND_HALF): true,
int64(FOOTBALL_SECOND_HALF_RESULT): true,
int64(FOOTBALL_CLEAN_SHEET): true,
int64(FOOTBALL_LAST_TEAM_TO_SCORE): true,
int64(FOOTBALL_WINNING_MARGIN): true,
int64(FOOTBALL_BOTH_TEAMS_TO_RECEIVE_CARDS): true,
int64(FOOTBALL_HALF_TIME_DOUBLE_CHANCE): true,
int64(FOOTBALL_HALF_TIME_RESULT_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_HALF_WITH_MOST_GOALS): true,
int64(FOOTBALL_HOME_TEAM_WITH_HIGHEST_SCORING_HALF): true,
int64(FOOTBALL_AWAY_TEAM_WITH_HIGHEST_SCORING_HALF): true,
int64(FOOTBALL_SECOND_HALF_GOALS): true,
int64(FOOTBALL_TEAM_TOTAL_GOALS): true,
int64(FOOTBALL_EXACT_TOTAL_GOALS): true,
int64(FOOTBALL_EXACT_FIRST_HALF_GOALS): true,
int64(FOOTBALL_TEAMS_TO_SCORE): true,
int64(FOOTBALL_EXACT_SECOND_HALF_GOALS): true,
int64(FOOTBALL_FIRST_MATCH_CORNER): true,
int64(FOOTBALL_LAST_MATCH_CORNER): true,
int64(FOOTBALL_CORNER_MATCH_BET): true,
int64(FOOTBALL_MULTI_CORNERS): true,
int64(FOOTBALL_MATCH_SHOTS_ON_TARGET): true,
int64(FOOTBALL_TEAM_SHOTS_ON_TARGET): true,
int64(FOOTBALL_SPECIALS): true,
int64(FOOTBALL_ASIAN_HANDICAP_CORNERS): true,
int64(FOOTBALL_CORNER_HANDICAP): true,
int64(FOOTBALL_ASIAN_TOTAL_CARDS): true,
int64(FOOTBALL_NUMBER_OF_CARDS_IN_MATCH): true,
int64(FOOTBALL_TIME_OF_FIRST_GOAL_BRACKETS): true,
int64(FOOTBALL_EARLY_GOAL): true,
int64(FOOTBALL_LATE_GOAL): true,
// Basketball Markets // Basketball Markets
int64(BASKETBALL_GAME_LINES): true, int64(BASKETBALL_GAME_LINES): true,
int64(BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS): true, int64(BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS): true,
@ -435,3 +477,49 @@ var SupportedMarkets = map[int64]bool{
// Baseball Markets // Baseball Markets
int64(BASEBALL_GAME_LINES): true, int64(BASEBALL_GAME_LINES): true,
} }
// These are temporarily disabled markets that will be disabled for all companies except for fortune
var DisabledMarkets = map[int64]bool{
int64(FOOTBALL_FULL_TIME_RESULT_ENHANCED): true,
int64(FOOTBALL_ALTERNATIVE_ASIAN_HANDICAP): true,
int64(FOOTBALL_ALTERNATIVE_GOAL_LINE): true,
int64(FOOTBALL_ALTERNATE_FIRST_HALF_ASIAN_HANDICAP): true,
int64(FOOTBALL_ALTERNATE_FIRST_HALF_GOAL_LINE): true,
int64(FOOTBALL_ALTERNATIVE_CORNER): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_RESULT_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_HALF_TIME_CORRECT_SCORE): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE_FIRST_HALF): true,
int64(FOOTBALL_BOTH_TEAMS_TO_SCORE_SECOND_HALF): true,
int64(FOOTBALL_SECOND_HALF_RESULT): true,
int64(FOOTBALL_CLEAN_SHEET): true,
int64(FOOTBALL_LAST_TEAM_TO_SCORE): true,
int64(FOOTBALL_WINNING_MARGIN): true,
int64(FOOTBALL_BOTH_TEAMS_TO_RECEIVE_CARDS): true,
int64(FOOTBALL_HALF_TIME_DOUBLE_CHANCE): true,
int64(FOOTBALL_HALF_TIME_RESULT_BOTH_TEAMS_TO_SCORE): true,
int64(FOOTBALL_HALF_WITH_MOST_GOALS): true,
int64(FOOTBALL_HOME_TEAM_WITH_HIGHEST_SCORING_HALF): true,
int64(FOOTBALL_AWAY_TEAM_WITH_HIGHEST_SCORING_HALF): true,
int64(FOOTBALL_SECOND_HALF_GOALS): true,
int64(FOOTBALL_TEAM_TOTAL_GOALS): true,
int64(FOOTBALL_EXACT_TOTAL_GOALS): true,
int64(FOOTBALL_EXACT_FIRST_HALF_GOALS): true,
int64(FOOTBALL_TEAMS_TO_SCORE): true,
int64(FOOTBALL_EXACT_SECOND_HALF_GOALS): true,
int64(FOOTBALL_FIRST_MATCH_CORNER): true,
int64(FOOTBALL_LAST_MATCH_CORNER): true,
int64(FOOTBALL_CORNER_MATCH_BET): true,
int64(FOOTBALL_MULTI_CORNERS): true,
int64(FOOTBALL_MATCH_SHOTS_ON_TARGET): true,
int64(FOOTBALL_TEAM_SHOTS_ON_TARGET): true,
int64(FOOTBALL_SPECIALS): true,
int64(FOOTBALL_ASIAN_HANDICAP_CORNERS): true,
int64(FOOTBALL_CORNER_HANDICAP): true,
int64(FOOTBALL_ASIAN_TOTAL_CARDS): true,
int64(FOOTBALL_NUMBER_OF_CARDS_IN_MATCH): true,
int64(FOOTBALL_TIME_OF_FIRST_GOAL_BRACKETS): true,
int64(FOOTBALL_EARLY_GOAL): true,
int64(FOOTBALL_LATE_GOAL): true,
}

View File

@ -0,0 +1,21 @@
package ports
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type MarketSettingStore interface {
InsertGlobalMarketSettings(ctx context.Context, setting domain.CreateGlobalMarketSettings) error
InsertCompanyMarketSettings(ctx context.Context, setting domain.CreateCompanyMarketSettings) error
GetAllGlobalMarketSettings(ctx context.Context, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error)
GetGlobalMarketSettingsByID(ctx context.Context, Id int64) (domain.MarketSettings, error)
GetAllCompanyMarketSettings(ctx context.Context, filter domain.CompanyMarketSettingFilter) ([]domain.CompanyMarketSettings, error)
GetCompanyMarketSettings(ctx context.Context, ID int64) (domain.CompanyMarketSettings, error)
GetAllOverrideMarketSettings(ctx context.Context, companyID int64, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error)
GetOverrideMarketSettingByID(ctx context.Context, companyID int64, marketID int64) (domain.MarketSettings, error)
DeleteAllCompanyMarketSettings(ctx context.Context, companyID int64) error
DeleteCompanyMarketSettings(ctx context.Context, companyID int64, marketID int64) error
EnsureAllMarketSettingsExist(ctx context.Context) error
}

View File

@ -21,4 +21,5 @@ type SettingStore interface {
GetOverrideSettingsList(ctx context.Context, companyID int64) (domain.SettingList, error) GetOverrideSettingsList(ctx context.Context, companyID int64) (domain.SettingList, error)
DeleteCompanySetting(ctx context.Context, companyID int64, key string) error DeleteCompanySetting(ctx context.Context, companyID int64, key string) error
DeleteAllCompanySetting(ctx context.Context, companyID int64) error DeleteAllCompanySetting(ctx context.Context, companyID int64) error
EnsureAllSettingsExist(ctx context.Context) error
} }

View File

@ -0,0 +1,187 @@
package repository
import (
"context"
"fmt"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/jackc/pgx/v5/pgtype"
)
func NewMarketSettingStore(s *Store) ports.MarketSettingStore { return s }
func (s *Store) InsertGlobalMarketSettings(ctx context.Context, setting domain.CreateGlobalMarketSettings) error {
err := s.queries.InsertGlobalMarketSettings(ctx, domain.ConvertCreateGlobalMarketSettings(setting))
if err != nil {
return err
}
return nil
}
func (s *Store) InsertCompanyMarketSettings(ctx context.Context, setting domain.CreateCompanyMarketSettings) error {
err := s.queries.InsertCompanyMarketSettings(ctx, domain.ConvertCreateCompanyMarketSettings(setting))
if err != nil {
return err
}
return nil
}
func (s *Store) GetAllGlobalMarketSettings(ctx context.Context, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error) {
settings, err := s.queries.GetAllGlobalMarketSettings(ctx, dbgen.GetAllGlobalMarketSettingsParams{
Offset: pgtype.Int4{
Int32: int32(filter.Offset.Value * filter.Limit.Value),
Valid: filter.Offset.Valid,
},
Limit: filter.Limit.ToPG(),
})
if err != nil {
return nil, err
}
return domain.ConvertDBGlobalMarketSettingsList(settings), nil
}
func (s *Store) GetGlobalMarketSettingsByID(ctx context.Context, Id int64) (domain.MarketSettings, error) {
setting, err := s.queries.GetGlobalMarketSettingsByID(ctx, Id)
if err != nil {
return domain.MarketSettings{}, err
}
return domain.ConvertDBGlobalMarketSettings(setting), nil
}
func (s *Store) GetAllCompanyMarketSettings(ctx context.Context, filter domain.CompanyMarketSettingFilter) ([]domain.CompanyMarketSettings, error) {
settings, err := s.queries.GetAllCompanyMarketSettings(ctx, dbgen.GetAllCompanyMarketSettingsParams{
Offset: pgtype.Int4{
Int32: int32(filter.Offset.Value * filter.Limit.Value),
Valid: filter.Offset.Valid,
},
Limit: filter.Limit.ToPG(),
CompanyID: filter.CompanyID.ToPG(),
})
if err != nil {
return nil, err
}
return domain.ConvertDBCompanyMarketSettingsList(settings), nil
}
func (s *Store) GetCompanyMarketSettings(ctx context.Context, ID int64) (domain.CompanyMarketSettings, error) {
setting, err := s.queries.GetCompanyMarketSettingsByID(ctx, ID)
if err != nil {
return domain.CompanyMarketSettings{}, err
}
return domain.ConvertDBCompanyMarketSettings(setting), nil
}
func (s *Store) GetAllOverrideMarketSettings(ctx context.Context, companyID int64, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error) {
settings, err := s.queries.GetAllOverrideMarketSettings(ctx, dbgen.GetAllOverrideMarketSettingsParams{
CompanyID: companyID,
Offset: pgtype.Int4{
Int32: int32(filter.Offset.Value * filter.Limit.Value),
Valid: filter.Offset.Valid,
},
Limit: filter.Limit.ToPG(),
})
if err != nil {
return nil, err
}
return domain.ConvertDBGetAllOverrideMarketSettingsList(settings), nil
}
func (s *Store) GetOverrideMarketSettingByID(ctx context.Context, companyID int64, marketID int64) (domain.MarketSettings, error) {
setting, err := s.queries.GetOverrideMarketSettingByID(ctx, dbgen.GetOverrideMarketSettingByIDParams{
CompanyID: companyID,
MarketID: marketID,
})
if err != nil {
return domain.MarketSettings{}, nil
}
return domain.ConvertDBGetOverrideMarketSettingsByID(setting), nil
}
func (s *Store) DeleteAllCompanyMarketSettings(ctx context.Context, companyID int64) error {
err := s.queries.DeleteAllMarketSettingsForCompany(ctx, companyID)
if err != nil {
return err
}
return nil
}
func (s *Store) DeleteCompanyMarketSettings(ctx context.Context, companyID int64, marketID int64) error {
err := s.queries.DeleteCompanyMarketSettings(ctx, dbgen.DeleteCompanyMarketSettingsParams{
MarketID: marketID,
CompanyID: companyID,
})
if err != nil {
return err
}
return nil
}
func (s *Store) EnsureAllMarketSettingsExist(ctx context.Context) error {
dbMarketSettings, err := s.GetAllGlobalMarketSettings(ctx, domain.MarketSettingFilter{})
if err != nil {
return fmt.Errorf("failed to fetch global market settings: %w", err)
}
dbCompanies, err := s.GetAllCompanies(ctx, domain.CompanyFilter{})
if err != nil {
return fmt.Errorf("failed to fetch companies: %w", err)
}
existing := map[int64]struct{}{}
for _, s := range dbMarketSettings {
existing[s.MarketID] = struct{}{}
}
for id, defaultIsActive := range domain.SupportedMarkets {
if _, found := existing[id]; !found {
name, err := domain.GetMarketName(id)
if err != nil {
return err
}
err = s.InsertGlobalMarketSettings(ctx, domain.CreateGlobalMarketSettings{
MarketID: id,
MarketName: name,
IsActive: defaultIsActive,
})
if err != nil{
return fmt.Errorf("failed to insert market %d (%s): %w", id, name, err)
}
}
// This is to auto disabled markets that haven't been tested yet
for _, company := range dbCompanies {
if company.Slug == "fortunebets" {
continue
}
if _, found := domain.DisabledMarkets[id]; !found {
continue
}
name, err := domain.GetMarketName(id)
err = s.InsertCompanyMarketSettings(ctx, domain.CreateCompanyMarketSettings{
CompanyID: company.ID,
MarketID: id,
MarketName: name,
IsActive: domain.ValidBool{
Value: false,
Valid: true,
},
})
if err != nil {
return fmt.Errorf("failed to insert company market %d (%s): %w", id, name, err)
}
}
}
return nil
}

View File

@ -118,7 +118,7 @@ func (s *Store) GetAllOddsWithSettings(ctx context.Context, companyID int64, fil
RawOdds: rawOdds, RawOdds: rawOdds,
FetchedAt: o.FetchedAt.Time, FetchedAt: o.FetchedAt.Time,
ExpiresAt: o.ExpiresAt.Time, ExpiresAt: o.ExpiresAt.Time,
IsActive: o.IsActive, IsActive: o.IsActive && o.IsMarketActive,
} }
} }
@ -194,7 +194,7 @@ func (s *Store) GetOddsWithSettingsByMarketID(ctx context.Context, marketID int6
RawOdds: rawOdds, RawOdds: rawOdds,
FetchedAt: odds.FetchedAt.Time, FetchedAt: odds.FetchedAt.Time,
ExpiresAt: odds.ExpiresAt.Time, ExpiresAt: odds.ExpiresAt.Time,
IsActive: odds.IsActive, IsActive: odds.IsActive && odds.IsMarketActive,
} }
return converted, nil return converted, nil
} }
@ -236,7 +236,7 @@ func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID
RawOdds: rawOdds, RawOdds: rawOdds,
FetchedAt: odds.FetchedAt.Time, FetchedAt: odds.FetchedAt.Time,
ExpiresAt: odds.ExpiresAt.Time, ExpiresAt: odds.ExpiresAt.Time,
IsActive: odds.IsActive, IsActive: odds.IsActive && odds.IsMarketActive,
} }
return converted, nil return converted, nil
@ -303,7 +303,7 @@ func (s *Store) GetOddsWithSettingsByEventID(ctx context.Context, eventID int64,
RawOdds: rawOdds, RawOdds: rawOdds,
FetchedAt: o.FetchedAt.Time, FetchedAt: o.FetchedAt.Time,
ExpiresAt: o.ExpiresAt.Time, ExpiresAt: o.ExpiresAt.Time,
IsActive: o.IsActive, IsActive: o.IsActive && o.IsMarketActive,
} }
} }

View File

@ -2,6 +2,7 @@ package repository
import ( import (
"context" "context"
"fmt"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
@ -12,6 +13,17 @@ import (
// Interface for creating new setting store // Interface for creating new setting store
func NewSettingStore(s *Store) ports.SettingStore { return s } func NewSettingStore(s *Store) ports.SettingStore { return s }
func (s *Store) InsertGlobalSetting(ctx context.Context, setting domain.CreateSetting) error {
err := s.queries.InsertGlobalSetting(ctx, dbgen.InsertGlobalSettingParams{
Key: setting.Key,
Value: setting.Value,
})
if err != nil {
return err
}
return nil
}
func (s *Store) GetGlobalSettingList(ctx context.Context) (domain.SettingList, error) { func (s *Store) GetGlobalSettingList(ctx context.Context) (domain.SettingList, error) {
settings, err := s.queries.GetGlobalSettings(ctx) settings, err := s.queries.GetGlobalSettings(ctx)
if err != nil { if err != nil {
@ -175,3 +187,30 @@ func (s *Store) DeleteCompanySetting(ctx context.Context, companyID int64, key s
func (s *Store) DeleteAllCompanySetting(ctx context.Context, companyID int64) error { func (s *Store) DeleteAllCompanySetting(ctx context.Context, companyID int64) error {
return s.queries.DeleteAllCompanySetting(ctx, companyID) return s.queries.DeleteAllCompanySetting(ctx, companyID)
} }
func (s *Store) EnsureAllSettingsExist(ctx context.Context) error {
defaultSettings := domain.NewDefaultSettingList().ToSettingArray() // returns []domain.Setting from your typed struct
dbSettings, err := s.GetGlobalSettings(ctx)
if err != nil {
return fmt.Errorf("failed to fetch settings: %w", err)
}
existing := map[string]struct{}{}
for _, s := range dbSettings {
existing[s.Key] = struct{}{}
}
for _, setting := range defaultSettings {
if _, found := existing[setting.Key]; !found {
if err := s.InsertGlobalSetting(ctx, domain.CreateSetting{
Key: setting.Key,
Value: setting.Value,
}); err != nil {
return fmt.Errorf("failed to create missing setting %q: %w", setting.Key, err)
}
}
}
return nil
}

View File

@ -141,6 +141,28 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
return domain.CreateBetOutcome{}, ErrEventHasNotEnded return domain.CreateBetOutcome{}, ErrEventHasNotEnded
} }
setting, err := s.prematchSvc.GetOverrideMarketSettingByID(ctx, companyID, marketID)
if err != nil {
s.mongoLogger.Error("failed to get override market settings by id",
zap.Int64("company_id", companyID),
zap.Int64("event_id", eventID),
zap.Int64("market_id", marketID),
zap.Error(err),
)
return domain.CreateBetOutcome{}, err
}
if !setting.IsActive {
s.mongoLogger.Error("Attempted to create bet on disabled market",
zap.Int64("event_id", eventID),
zap.Int64("market_id", marketID),
zap.Int64("company_id", companyID),
zap.Error(err),
)
return domain.CreateBetOutcome{}, ErrOddHasBeenDisabled
}
odds, err := s.prematchSvc.GetOddsWithSettingsByMarketID(ctx, marketID, eventID, companyID) odds, err := s.prematchSvc.GetOddsWithSettingsByMarketID(ctx, marketID, eventID, companyID)
if err != nil { if err != nil {
s.mongoLogger.Error("failed to get raw odds by market ID", s.mongoLogger.Error("failed to get raw odds by market ID",
@ -152,7 +174,7 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
} }
if !odds.IsActive { if !odds.IsActive {
s.mongoLogger.Error("failed to get raw odds by market ID", s.mongoLogger.Info("Attempted to created bet on disabled odd",
zap.Int64("event_id", eventID), zap.Int64("event_id", eventID),
zap.Int64("market_id", marketID), zap.Int64("market_id", marketID),
zap.Error(err), zap.Error(err),
@ -160,6 +182,7 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
return domain.CreateBetOutcome{}, ErrOddHasBeenDisabled return domain.CreateBetOutcome{}, ErrOddHasBeenDisabled
} }
type rawOddType struct { type rawOddType struct {
ID string ID string
Name string Name string

View File

@ -0,0 +1,38 @@
package odds
import (
"context"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
func (s *ServiceImpl) InsertGlobalMarketSettings(ctx context.Context, setting domain.CreateGlobalMarketSettings) error {
return s.marketSettingStore.InsertGlobalMarketSettings(ctx, setting)
}
func (s *ServiceImpl) InsertCompanyMarketSettings(ctx context.Context, setting domain.CreateCompanyMarketSettings) error {
return s.marketSettingStore.InsertCompanyMarketSettings(ctx, setting)
}
func (s *ServiceImpl) GetAllGlobalMarketSettings(ctx context.Context, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error) {
return s.marketSettingStore.GetAllGlobalMarketSettings(ctx, filter)
}
func (s *ServiceImpl) GetGlobalMarketSettingsByID(ctx context.Context, Id int64) (domain.MarketSettings, error) {
return s.marketSettingStore.GetGlobalMarketSettingsByID(ctx, Id)
}
func (s *ServiceImpl) GetAllCompanyMarketSettings(ctx context.Context, filter domain.CompanyMarketSettingFilter) ([]domain.CompanyMarketSettings, error) {
return s.marketSettingStore.GetAllCompanyMarketSettings(ctx, filter)
}
func (s *ServiceImpl) GetCompanyMarketSettings(ctx context.Context, ID int64) (domain.CompanyMarketSettings, error) {
return s.marketSettingStore.GetCompanyMarketSettings(ctx, ID)
}
func (s *ServiceImpl) GetAllOverrideMarketSettings(ctx context.Context, companyID int64, filter domain.MarketSettingFilter) ([]domain.MarketSettings, error) {
return s.marketSettingStore.GetAllOverrideMarketSettings(ctx, companyID, filter)
}
func (s *ServiceImpl) GetOverrideMarketSettingByID(ctx context.Context, companyID int64, marketID int64) (domain.MarketSettings, error) {
return s.marketSettingStore.GetOverrideMarketSettingByID(ctx, companyID, marketID)
}
func (s *ServiceImpl) DeleteAllCompanyMarketSettings(ctx context.Context, companyID int64) error {
return s.marketSettingStore.DeleteAllCompanyMarketSettings(ctx, companyID)
}
func (s *ServiceImpl) DeleteCompanyMarketSettings(ctx context.Context, companyID int64, marketID int64) error {
return s.marketSettingStore.DeleteCompanyMarketSettings(ctx, companyID, marketID)
}

View File

@ -22,22 +22,24 @@ import (
) )
type ServiceImpl struct { type ServiceImpl struct {
store ports.OddStore store ports.OddStore
config *config.Config marketSettingStore ports.MarketSettingStore
eventSvc *event.Service config *config.Config
logger *slog.Logger eventSvc *event.Service
mongoLogger *zap.Logger logger *slog.Logger
client *http.Client mongoLogger *zap.Logger
client *http.Client
} }
func New(store ports.OddStore, cfg *config.Config, eventSvc *event.Service, logger *slog.Logger, mongoLogger *zap.Logger) *ServiceImpl { func New(store ports.OddStore, marketSettingStore ports.MarketSettingStore, cfg *config.Config, eventSvc *event.Service, logger *slog.Logger, mongoLogger *zap.Logger) *ServiceImpl {
return &ServiceImpl{ return &ServiceImpl{
store: store, store: store,
config: cfg, marketSettingStore: marketSettingStore,
eventSvc: eventSvc, config: cfg,
logger: logger, eventSvc: eventSvc,
mongoLogger: mongoLogger, logger: logger,
client: &http.Client{Timeout: 10 * time.Second}, mongoLogger: mongoLogger,
client: &http.Client{Timeout: 10 * time.Second},
} }
} }

View File

@ -37,86 +37,86 @@ func StartBetAPIDataFetchingCrons(
spec string spec string
task func() task func()
}{ }{
{ // {
spec: "0 0 * * * *", // Every 1 hour // spec: "0 0 * * * *", // Every 1 hour
task: func() { // task: func() {
start := time.Now() // start := time.Now()
mongoLogger.Info("[BetAPI Event Fetching Crons] Began fetching upcoming events cron task", zap.Time("timestamp", time.Now())) // mongoLogger.Info("[BetAPI Event Fetching Crons] Began fetching upcoming events cron task", zap.Time("timestamp", time.Now()))
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil { // if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
mongoLogger.Error("[BetAPI Event Fetching Crons] Failed to fetch upcoming events", // mongoLogger.Error("[BetAPI Event Fetching Crons] Failed to fetch upcoming events",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
zap.Error(err), // zap.Error(err),
) // )
} else { // } else {
mongoLogger.Info("[BetAPI Event Fetching Crons] Completed fetching upcoming events without errors", // mongoLogger.Info("[BetAPI Event Fetching Crons] Completed fetching upcoming events without errors",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} // }
}, // },
}, // },
{ // {
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events) // spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
task: func() { // task: func() {
start := time.Now() // start := time.Now()
mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Began fetching pre-match odds cron task", // mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Began fetching pre-match odds cron task",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { // if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
mongoLogger.Error("[BetAPI Pre-Match Odds Fetching Crons] Failed to fetch pre-match odds", // mongoLogger.Error("[BetAPI Pre-Match Odds Fetching Crons] Failed to fetch pre-match odds",
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} else { // } else {
mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Completed fetching pre-match odds without errors", // mongoLogger.Info("[BetAPI Pre-Match Odds Fetching Crons] Completed fetching pre-match odds without errors",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} // }
}, // },
}, // },
{ // {
spec: "0 */5 * * * *", // Every 5 Minutes // spec: "0 */5 * * * *", // Every 5 Minutes
task: func() { // task: func() {
start := time.Now() // start := time.Now()
mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Began update all expired events status cron task", // mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Began update all expired events status cron task",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
) // )
if _, err := resultService.CheckAndUpdateExpiredB365Events(context.Background()); err != nil { // if _, err := resultService.CheckAndUpdateExpiredB365Events(context.Background()); err != nil {
mongoLogger.Error("[BetAPI Check And Update Expired Events Crons] Failed to update expired events status", // mongoLogger.Error("[BetAPI Check And Update Expired Events Crons] Failed to update expired events status",
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} else { // } else {
mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Completed expired events without errors", // mongoLogger.Info("[BetAPI Check And Update Expired Events Crons] Completed expired events without errors",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} // }
}, // },
}, // },
{ // {
spec: "0 */15 * * * *", // Every 15 Minutes // spec: "0 */15 * * * *", // Every 15 Minutes
task: func() { // task: func() {
start := time.Now() // start := time.Now()
mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Began updating bets based on event results cron task") // mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Began updating bets based on event results cron task")
if err := resultService.FetchB365ResultAndUpdateBets(context.Background()); err != nil { // if err := resultService.FetchB365ResultAndUpdateBets(context.Background()); err != nil {
mongoLogger.Error("[BetAPI Fetch Result and Update Bets Crons] Failed to process result", // mongoLogger.Error("[BetAPI Fetch Result and Update Bets Crons] Failed to process result",
zap.Error(err), // zap.Error(err),
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} else { // } else {
mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Completed processing all event result outcomes without errors", // mongoLogger.Info("[BetAPI Fetch Result and Update Bets Crons] Completed processing all event result outcomes without errors",
zap.Time("timestamp", time.Now()), // zap.Time("timestamp", time.Now()),
zap.Duration("duration", time.Since(start)), // zap.Duration("duration", time.Since(start)),
) // )
} // }
}, // },
}, // },
// { // {
// spec: "0 0 0 * * 1", // Every Monday // spec: "0 0 0 * * 1", // Every Monday
// task: func() { // task: func() {

View File

@ -22,7 +22,7 @@ import (
// @Router /api/v1/leagues [get] // @Router /api/v1/leagues [get]
func (h *Handler) GetAllLeagues(c *fiber.Ctx) error { func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
page := c.QueryInt("page", 1) page := c.QueryInt("page", 1)
pageSize := c.QueryInt("page_size", 10) pageSize := c.QueryInt("page_size", 0)
limit := domain.ValidInt64{ limit := domain.ValidInt64{
Value: int64(pageSize), Value: int64(pageSize),
@ -30,7 +30,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
} }
offset := domain.ValidInt64{ offset := domain.ValidInt64{
Value: int64(page - 1), Value: int64(page - 1),
Valid: true, Valid: page != 1,
} }
searchQuery := c.Query("query") searchQuery := c.Query("query")

View File

@ -0,0 +1,195 @@
package handlers
import (
"fmt"
"strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
// InsertCompanyMarketSettings
// @Summary Insert company-specific market settings
// @Description Insert new market settings for a specific tenant/company
// @Tags market_settings
// @Accept json
// @Produce json
// @Param body body domain.CreateCompanyMarketSettings true "Market Settings"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/market-settings [post]
func (h *Handler) InsertCompanyMarketSettings(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
var req domain.CreateCompanyMarketSettingsReq
if err := c.BodyParser(&req); err != nil {
h.BadRequestLogger().Info("Failed to parse request", zap.Int64("company_id", companyID.Value), zap.Error(err))
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
errMsg := ""
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.BadRequestLogger().Error("Validation failed", zap.String("errors", errMsg))
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
if err := h.prematchSvc.InsertCompanyMarketSettings(c.Context(), domain.ConvertCreateCompanyMarketSettingsReq(
req, companyID.Value,
)); err != nil {
h.InternalServerErrorLogger().Error("Failed to insert company market settings", zap.Int64("company_id", companyID.Value), zap.Error(err))
return fiber.NewError(fiber.StatusInternalServerError, "Failed to insert market settings: "+err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Company market settings inserted successfully", nil, nil)
}
// GetAllGlobalMarketSettings
// @Summary Retrieve all global market settings
// @Description Get all market settings that apply globally
// @Tags market_settings
// @Accept json
// @Produce json
// @Param limit query int false "Number of results to return (default 10)"
// @Param offset query int false "Number of results to skip (default 0)"
// @Success 200 {array} domain.MarketSettings
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/market-settings [get]
func (h *Handler) GetAllGlobalMarketSettings(c *fiber.Ctx) error {
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil || limit <= 0 {
h.BadRequestLogger().Info("Invalid limit value", zap.Error(err))
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
}
offset, err := strconv.Atoi(c.Query("offset", "0"))
if err != nil || offset < 0 {
h.BadRequestLogger().Info("Invalid offset value", zap.Error(err))
return fiber.NewError(fiber.StatusBadRequest, "Invalid offset value")
}
settings, err := h.prematchSvc.GetAllGlobalMarketSettings(c.Context(), domain.MarketSettingFilter{
Limit: domain.ValidInt32{Value: int32(limit), Valid: true},
Offset: domain.ValidInt32{Value: int32(offset), Valid: true},
})
if err != nil {
h.InternalServerErrorLogger().Error("Failed to retrieve global market settings", zap.Error(err))
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve global market settings: "+err.Error())
}
res := domain.ConvertMarketSettingsResList(settings)
return response.WriteJSON(c, fiber.StatusOK, "Global market settings retrieved successfully", res, nil)
}
// GetAllTenantMarketSettings
// @Summary Retrieve all market settings for a tenant
// @Description Get all market settings overridden for a specific tenant
// @Tags market_settings
// @Accept json
// @Produce json
// @Param limit query int false "Number of results to return (default 10)"
// @Param offset query int false "Number of results to skip (default 0)"
// @Success 200 {array} domain.CompanyMarketSettings
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/market-settings [get]
func (h *Handler) GetAllTenantMarketSettings(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil || limit <= 0 {
h.BadRequestLogger().Info("Invalid limit value", zap.Error(err))
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
}
offset, err := strconv.Atoi(c.Query("offset", "0"))
if err != nil || offset < 0 {
h.BadRequestLogger().Info("Invalid offset value", zap.Error(err))
return fiber.NewError(fiber.StatusBadRequest, "Invalid offset value")
}
settings, err := h.prematchSvc.GetAllOverrideMarketSettings(c.Context(), companyID.Value, domain.MarketSettingFilter{
Limit: domain.ValidInt32{Value: int32(limit), Valid: true},
Offset: domain.ValidInt32{Value: int32(offset), Valid: true},
})
if err != nil {
h.InternalServerErrorLogger().Error("Failed to retrieve tenant market settings", zap.Int64("company_id", companyID.Value), zap.Error(err))
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve tenant market settings: "+err.Error())
}
res := domain.ConvertMarketSettingsResList(settings)
return response.WriteJSON(c, fiber.StatusOK, "Tenant market settings retrieved successfully", res, nil)
}
// DeleteAllCompanyMarketSettings
// @Summary Delete all market settings for a tenant
// @Description Remove all overridden market settings for a specific tenant
// @Tags market_settings
// @Accept json
// @Produce json
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/market-settings [delete]
func (h *Handler) DeleteAllCompanyMarketSettings(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
if err := h.prematchSvc.DeleteAllCompanyMarketSettings(c.Context(), companyID.Value); err != nil {
h.InternalServerErrorLogger().Error("Failed to delete all company market settings", zap.Int64("company_id", companyID.Value), zap.Error(err))
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete all company market settings: "+err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "All tenant market settings removed successfully", nil, nil)
}
// DeleteCompanyMarketSettings
// @Summary Delete a specific market setting for a tenant
// @Description Remove a specific overridden market setting for a tenant
// @Tags market_settings
// @Accept json
// @Produce json
// @Param id path int true "Market ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/market-settings/{id} [delete]
func (h *Handler) DeleteCompanyMarketSettings(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
marketIDStr := c.Params("id")
marketID, err := strconv.ParseInt(marketIDStr, 10, 64)
if err != nil {
h.BadRequestLogger().Info("Failed to parse market id", zap.String("id", marketIDStr))
return fiber.NewError(fiber.StatusBadRequest, "Invalid market id")
}
if err := h.prematchSvc.DeleteCompanyMarketSettings(c.Context(), companyID.Value, marketID); err != nil {
h.InternalServerErrorLogger().Error("Failed to delete company market setting", zap.Int64("company_id", companyID.Value), zap.Int64("market_id", marketID), zap.Error(err))
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete market setting: "+err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Tenant market setting removed successfully", nil, nil)
}

View File

@ -53,7 +53,7 @@ func (a *App) initAppRoutes() {
a.prematchSvc, a.prematchSvc,
a.eventSvc, a.eventSvc,
a.leagueSvc, a.leagueSvc,
*a.resultSvc, *a.resultSvc,
a.statSvc, a.statSvc,
a.cfg, a.cfg,
a.mongoLoggerSvc, a.mongoLoggerSvc,
@ -260,15 +260,20 @@ func (a *App) initAppRoutes() {
groupV1.Get("/odds/upcoming/:upcoming_id", a.authMiddleware, a.SuperAdminOnly, h.GetOddsByUpcomingID) groupV1.Get("/odds/upcoming/:upcoming_id", a.authMiddleware, a.SuperAdminOnly, h.GetOddsByUpcomingID)
groupV1.Get("/odds/upcoming/:upcoming_id/market/:market_id", a.authMiddleware, a.SuperAdminOnly, h.GetOddsByMarketID) groupV1.Get("/odds/upcoming/:upcoming_id/market/:market_id", a.authMiddleware, a.SuperAdminOnly, h.GetOddsByMarketID)
groupV1.Post("/odds/settings", a.authMiddleware, a.SuperAdminOnly, h.SaveOddSettings) groupV1.Post("/odds/settings", a.authMiddleware, a.SuperAdminOnly, h.SaveOddSettings)
groupV1.Get("/odds/market-settings", a.authMiddleware, a.SuperAdminOnly, h.GetAllGlobalMarketSettings)
groupV1.Put("/odds/bet-outcome/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateAllBetOutcomeStatusByOddID) groupV1.Put("/odds/bet-outcome/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateAllBetOutcomeStatusByOddID)
groupV1.Put("/odds/bet-outcome", a.authMiddleware, a.SuperAdminOnly, h.BulkUpdateAllBetOutcomeStatusByOddID) groupV1.Put("/odds/bet-outcome", a.authMiddleware, a.SuperAdminOnly, h.BulkUpdateAllBetOutcomeStatusByOddID)
tenant.Get("/odds", h.GetAllTenantOdds) tenant.Get("/odds", h.GetAllTenantOdds)
tenant.Get("/odds/upcoming/:upcoming_id", h.GetTenantOddsByUpcomingID) tenant.Get("/odds/upcoming/:upcoming_id", h.GetTenantOddsByUpcomingID)
tenant.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetTenantOddsByMarketID) tenant.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetTenantOddsByMarketID)
tenant.Post("/odds/settings", a.CompanyOnly, h.SaveTenantOddsSetting) tenant.Post("/odds/settings", a.authMiddleware, a.CompanyOnly, h.SaveTenantOddsSetting)
tenant.Delete("/odds/settings/:id", a.CompanyOnly, h.RemoveOddsSettings) tenant.Delete("/odds/settings/:id", a.authMiddleware, a.CompanyOnly, h.RemoveOddsSettings)
tenant.Delete("/odds/settings", a.CompanyOnly, h.RemoveAllOddsSettings) tenant.Delete("/odds/settings", a.authMiddleware, a.CompanyOnly, h.RemoveAllOddsSettings)
tenant.Post("/odds/market-settings", a.authMiddleware, a.CompanyOnly, h.InsertCompanyMarketSettings)
tenant.Get("/odds/market-settings", a.authMiddleware, a.CompanyOnly, h.GetAllTenantMarketSettings)
tenant.Delete("/odds/market-settings", a.authMiddleware, a.CompanyOnly, h.DeleteAllCompanyMarketSettings)
tenant.Delete("/odds/market-settings/:id", a.authMiddleware, a.CompanyOnly, h.DeleteCompanyMarketSettings)
groupV1.Get("/events", a.authMiddleware, h.GetAllEvents) groupV1.Get("/events", a.authMiddleware, h.GetAllEvents)
groupV1.Get("/events/:id", a.authMiddleware, h.GetEventByID) groupV1.Get("/events/:id", a.authMiddleware, h.GetEventByID)