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())
// 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)
statSvc := stats.NewService(
repository.NewCompanyStatStore(store),
@ -142,13 +148,21 @@ func main() {
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(
repository.NewOddStore(store),
marketSettingRepo,
cfg,
eventSvc,
logger,
domain.MongoDBLogger,
)
// virtuaGamesRepo := repository.NewVirtualGameRepository(store)
// Initialize producer

View File

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

View File

@ -438,6 +438,21 @@ CREATE TABLE company_odd_settings (
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
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 (
id BIGSERIAL PRIMARY KEY,
status_not_finished_count INT NOT NULL,
@ -750,7 +765,7 @@ FROM customer_wallets cw
LEFT JOIN LATERAL (
SELECT *
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
LIMIT 1
) cs ON true;
@ -884,10 +899,12 @@ SELECT o.id,
o.expires_at,
cos.company_id,
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,
cos.updated_at
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
SELECT r.*,
c.name AS company_name,

View File

@ -5,7 +5,7 @@ bet_stats AS (
COUNT(*) AS total_bets,
COALESCE(SUM(amount), 0) AS total_stake,
COALESCE(
SUM(amount) * MAX(companies.deducted_percentage),
SUM(amount) * MAX(profit_percent),
0
) AS deducted_stake,
COALESCE(
@ -71,18 +71,18 @@ SELECT br.id AS branch_id,
c.name AS company_name,
c.slug AS company_slug,
DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start,
COALESCE(b.total_bets, 0) AS total_bets,
COALESCE(b.total_stake, 0) AS total_stake,
COALESCE(b.deducted_stake, 0) AS deducted_stake,
COALESCE(b.total_cash_out, 0) AS total_cash_out,
COALESCE(b.total_cash_backs, 0) AS total_cash_backs,
COALESCE(b.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(b.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bs.total_bets, 0) AS total_bets,
COALESCE(bs.total_stake, 0) AS total_stake,
COALESCE(bs.deducted_stake, 0) AS deducted_stake,
COALESCE(bs.total_cash_out, 0) AS total_cash_out,
COALESCE(bs.total_cash_backs, 0) AS total_cash_backs,
COALESCE(bs.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(bs.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bc.total_cashiers, 0) AS total_cashiers,
NOW() AS updated_at
FROM branches br
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
UPDATE
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_admins = EXCLUDED.total_admins,
total_managers = EXCLUDED.total_managers,
SETtotal_cashiers = EXCLUDED.total_cashiers,
total_cashiers = EXCLUDED.total_cashiers,
total_customers = EXCLUDED.total_customers,
total_approvers = EXCLUDED.total_approvers,
total_branches = EXCLUDED.total_branches,

View File

@ -83,7 +83,7 @@ SELECT e.*,
FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
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
LEFT JOIN (
SELECT event_id,
@ -157,9 +157,9 @@ SELECT e.*,
COALESCE(ebs.avg_bet_amount, 0) AS avg_bet_amount,
COALESCE(ebs.total_potential_winnings, 0) AS total_potential_winnings
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
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
LEFT JOIN (
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,
$6,
$7,
$8,
$8,
$9
) ON CONFLICT (event_id, market_id) DO
UPDATE
@ -57,11 +57,14 @@ SELECT o.id,
o.expires_at,
cos.company_id,
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,
cos.updated_at
FROM odds_market o
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');
-- name: GetOddByID :one
SELECT *
@ -85,12 +88,15 @@ SELECT o.id,
o.expires_at,
cos.company_id,
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,
cos.updated_at
FROM odds_market o
LEFT JOIN company_odd_settings cos ON o.id = cos.odds_market_id
AND company_id = $3
WHERE market_id = $1
AND cos.company_id = $3
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;
-- name: GetOddsWithSettingsByID :one
SELECT o.id,
@ -105,11 +111,14 @@ SELECT o.id,
o.expires_at,
cos.company_id,
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,
cos.updated_at
FROM odds_market o
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;
-- name: GetOddsByEventID :many
SELECT *
@ -141,11 +150,14 @@ SELECT o.id,
o.expires_at,
cos.company_id,
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,
cos.updated_at
FROM odds_market o
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
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- 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
SELECT *
FROM global_settings;

View File

@ -150,7 +150,7 @@ bet_stats AS (
COUNT(*) AS total_bets,
COALESCE(SUM(amount), 0) AS total_stake,
COALESCE(
SUM(amount) * MAX(companies.deducted_percentage),
SUM(amount) * MAX(profit_percent),
0
) AS deducted_stake,
COALESCE(
@ -216,18 +216,18 @@ SELECT br.id AS branch_id,
c.name AS company_name,
c.slug AS company_slug,
DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC') AS interval_start,
COALESCE(b.total_bets, 0) AS total_bets,
COALESCE(b.total_stake, 0) AS total_stake,
COALESCE(b.deducted_stake, 0) AS deducted_stake,
COALESCE(b.total_cash_out, 0) AS total_cash_out,
COALESCE(b.total_cash_backs, 0) AS total_cash_backs,
COALESCE(b.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(b.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bs.total_bets, 0) AS total_bets,
COALESCE(bs.total_stake, 0) AS total_stake,
COALESCE(bs.deducted_stake, 0) AS deducted_stake,
COALESCE(bs.total_cash_out, 0) AS total_cash_out,
COALESCE(bs.total_cash_backs, 0) AS total_cash_backs,
COALESCE(bs.number_of_unsettled, 0) AS number_of_unsettled,
COALESCE(bs.total_unsettled_amount, 0) AS total_unsettled_amount,
COALESCE(bc.total_cashiers, 0) AS total_cashiers,
NOW() AS updated_at
FROM branches br
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
UPDATE
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_admins = EXCLUDED.total_admins,
total_managers = EXCLUDED.total_managers,
SETtotal_cashiers = EXCLUDED.total_cashiers,
total_cashiers = EXCLUDED.total_cashiers,
total_customers = EXCLUDED.total_customers,
total_approvers = EXCLUDED.total_approvers,
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.total_potential_winnings, 0) AS total_potential_winnings
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
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
LEFT JOIN (
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
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
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
LEFT JOIN (
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"`
}
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 {
ID int64 `json:"id"`
CompanyID int64 `json:"company_id"`
@ -518,6 +526,13 @@ type Flag struct {
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 {
Key string `json:"key"`
Value string `json:"value"`
@ -625,6 +640,7 @@ type OddsMarketWithSetting struct {
ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
IsMarketActive bool `json:"is_market_active"`
RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}

View File

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

View File

@ -240,6 +240,23 @@ func (q *Queries) InsertCompanySetting(ctx context.Context, arg InsertCompanySet
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
UPDATE global_settings
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,
FetchedAt: oms.FetchedAt.Time,
ExpiresAt: oms.ExpiresAt.Time,
IsActive: oms.IsActive,
IsActive: oms.IsActive && oms.IsMarketActive,
}, nil
}

View File

@ -40,6 +40,63 @@ type SettingList struct {
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 {
SMSProvider SMSProvider `json:"sms_provider"`
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 == ErrSettingNotFound {
MongoDBLogger.Warn("unknown setting found on database", zap.String("setting", setting.Key))
continue
}
MongoDBLogger.Error("unknown error while fetching settings", zap.Error(err))
}

View File

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

View File

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

View File

@ -2,6 +2,7 @@ package repository
import (
"context"
"fmt"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
@ -12,6 +13,17 @@ import (
// Interface for creating new setting store
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) {
settings, err := s.queries.GetGlobalSettings(ctx)
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 {
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
}
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)
if err != nil {
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 {
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("market_id", marketID),
zap.Error(err),
@ -160,6 +182,7 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
return domain.CreateBetOutcome{}, ErrOddHasBeenDisabled
}
type rawOddType struct {
ID 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 {
store ports.OddStore
config *config.Config
eventSvc *event.Service
logger *slog.Logger
mongoLogger *zap.Logger
client *http.Client
store ports.OddStore
marketSettingStore ports.MarketSettingStore
config *config.Config
eventSvc *event.Service
logger *slog.Logger
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{
store: store,
config: cfg,
eventSvc: eventSvc,
logger: logger,
mongoLogger: mongoLogger,
client: &http.Client{Timeout: 10 * time.Second},
store: store,
marketSettingStore: marketSettingStore,
config: cfg,
eventSvc: eventSvc,
logger: logger,
mongoLogger: mongoLogger,
client: &http.Client{Timeout: 10 * time.Second},
}
}

View File

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

View File

@ -22,7 +22,7 @@ import (
// @Router /api/v1/leagues [get]
func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("page_size", 10)
pageSize := c.QueryInt("page_size", 0)
limit := domain.ValidInt64{
Value: int64(pageSize),
@ -30,7 +30,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
}
offset := domain.ValidInt64{
Value: int64(page - 1),
Valid: true,
Valid: page != 1,
}
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.eventSvc,
a.leagueSvc,
*a.resultSvc,
*a.resultSvc,
a.statSvc,
a.cfg,
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/market/:market_id", a.authMiddleware, a.SuperAdminOnly, h.GetOddsByMarketID)
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", a.authMiddleware, a.SuperAdminOnly, h.BulkUpdateAllBetOutcomeStatusByOddID)
tenant.Get("/odds", h.GetAllTenantOdds)
tenant.Get("/odds/upcoming/:upcoming_id", h.GetTenantOddsByUpcomingID)
tenant.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetTenantOddsByMarketID)
tenant.Post("/odds/settings", a.CompanyOnly, h.SaveTenantOddsSetting)
tenant.Delete("/odds/settings/:id", a.CompanyOnly, h.RemoveOddsSettings)
tenant.Delete("/odds/settings", a.CompanyOnly, h.RemoveAllOddsSettings)
tenant.Post("/odds/settings", a.authMiddleware, a.CompanyOnly, h.SaveTenantOddsSetting)
tenant.Delete("/odds/settings/:id", a.authMiddleware, a.CompanyOnly, h.RemoveOddsSettings)
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/:id", a.authMiddleware, h.GetEventByID)