fix: resolved issue on event, odds and creating a bet

This commit is contained in:
Samuel Tariku 2025-09-03 03:16:37 +03:00
parent 1c7c7e5731
commit 6b09c3c8d2
38 changed files with 952 additions and 328 deletions

View File

@ -112,13 +112,11 @@ func main() {
authSvc := authentication.NewService(store, store, cfg.RefreshExpiry) authSvc := authentication.NewService(store, store, cfg.RefreshExpiry)
userSvc := user.NewService(store, store, messengerSvc, cfg) userSvc := user.NewService(store, store, messengerSvc, cfg)
eventSvc := event.New(cfg.Bet365Token, store, domain.MongoDBLogger) eventSvc := event.New(cfg.Bet365Token, store, *settingSvc, domain.MongoDBLogger)
oddsSvc := odds.New(store, cfg, eventSvc, logger, domain.MongoDBLogger) oddsSvc := odds.New(store, cfg, eventSvc, logger, domain.MongoDBLogger)
notificationRepo := repository.NewNotificationRepository(store) notificationRepo := repository.NewNotificationRepository(store)
virtuaGamesRepo := repository.NewVirtualGameRepository(store) virtuaGamesRepo := repository.NewVirtualGameRepository(store)
notificationSvc := notificationservice.New(notificationRepo, domain.MongoDBLogger, logger, cfg, messengerSvc, userSvc) notificationSvc := notificationservice.New(notificationRepo, domain.MongoDBLogger, logger, cfg, messengerSvc, userSvc)
var notificatioStore notificationservice.NotificationStore
// var userStore user.UserStore // var userStore user.UserStore
// Initialize producer // Initialize producer
@ -130,7 +128,6 @@ func main() {
wallet.WalletStore(store), wallet.WalletStore(store),
wallet.TransferStore(store), wallet.TransferStore(store),
wallet.DirectDepositStore(store), wallet.DirectDepositStore(store),
notificatioStore,
notificationSvc, notificationSvc,
userSvc, userSvc,
domain.MongoDBLogger, domain.MongoDBLogger,
@ -153,7 +150,7 @@ func main() {
virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger)
aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger)
veliCLient := veli.NewClient(cfg, walletSvc) veliCLient := veli.NewClient(cfg, walletSvc)
veliVirtualGameService := veli.New(virtualGameSvc,vitualGameRepo, veliCLient, walletSvc, wallet.TransferStore(store), cfg) veliVirtualGameService := veli.New(virtualGameSvc, vitualGameRepo, veliCLient, walletSvc, wallet.TransferStore(store), cfg)
recommendationSvc := recommendation.NewService(recommendationRepo) recommendationSvc := recommendation.NewService(recommendationRepo)
chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY) chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY)

View File

@ -1,5 +1,4 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Locations Initial Data -- Locations Initial Data
INSERT INTO branch_locations (key, value) INSERT INTO branch_locations (key, value)
VALUES ('addis_ababa', 'Addis Ababa'), VALUES ('addis_ababa', 'Addis Ababa'),
@ -75,7 +74,6 @@ VALUES ('addis_ababa', 'Addis Ababa'),
('agaro', 'Agaro') ON CONFLICT (key) DO ('agaro', 'Agaro') ON CONFLICT (key) DO
UPDATE UPDATE
SET value = EXCLUDED.value; SET value = EXCLUDED.value;
-- Settings Initial Data -- Settings Initial Data
INSERT INTO global_settings (key, value) INSERT INTO global_settings (key, value)
VALUES ('sms_provider', 'afro_message'), VALUES ('sms_provider', 'afro_message'),
@ -84,8 +82,8 @@ VALUES ('sms_provider', 'afro_message'),
('daily_ticket_limit', '50'), ('daily_ticket_limit', '50'),
('total_winnings_limit', '1000000'), ('total_winnings_limit', '1000000'),
('amount_for_bet_referral', '1000000'), ('amount_for_bet_referral', '1000000'),
('cashback_amount_cap', '1000') ON CONFLICT (key) DO NOTHING; ('cashback_amount_cap', '1000'),
('default_winning_limit', '5000000') ON CONFLICT (key) DO NOTHING;
-- Users -- Users
INSERT INTO users ( INSERT INTO users (
id, id,
@ -224,7 +222,7 @@ VALUES (
), ),
( (
3, 3,
20000, 100000000 ,
TRUE, TRUE,
TRUE, TRUE,
TRUE, TRUE,
@ -237,7 +235,7 @@ VALUES (
), ),
( (
4, 4,
15000, 50000000,
TRUE, TRUE,
TRUE, TRUE,
TRUE, TRUE,

View File

@ -33,7 +33,7 @@ VALUES (
6, 6,
'Kirubel', 'Kirubel',
'Kibru', 'Kibru',
'modernkibru @gmail.com', 'modernkibru@gmail.com',
NULL, NULL,
crypt('password@123', gen_salt('bf'))::bytea, crypt('password@123', gen_salt('bf'))::bytea,
'customer', 'customer',
@ -98,7 +98,7 @@ VALUES (
), ),
( (
7, 7,
10000, 1000000,
TRUE, TRUE,
TRUE, TRUE,
TRUE, TRUE,

View File

@ -36,7 +36,6 @@ CREATE TABLE IF NOT EXISTS virtual_game_providers (
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ updated_at TIMESTAMPTZ
); );
CREATE TABLE IF NOT EXISTS virtual_games ( CREATE TABLE IF NOT EXISTS virtual_games (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
game_id VARCHAR(150) NOT NULL, game_id VARCHAR(150) NOT NULL,
@ -45,19 +44,16 @@ CREATE TABLE IF NOT EXISTS virtual_games (
category VARCHAR(100), category VARCHAR(100),
device_type VARCHAR(100), device_type VARCHAR(100),
volatility VARCHAR(50), volatility VARCHAR(50),
rtp NUMERIC(5,2), rtp NUMERIC(5, 2),
has_demo BOOLEAN DEFAULT FALSE, has_demo BOOLEAN DEFAULT FALSE,
has_free_bets BOOLEAN DEFAULT FALSE, has_free_bets BOOLEAN DEFAULT FALSE,
bets NUMERIC[] DEFAULT '{}', bets NUMERIC [] DEFAULT '{}',
thumbnail TEXT, thumbnail TEXT,
status INT, status INT,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ updated_at TIMESTAMPTZ
); );
CREATE UNIQUE INDEX IF NOT EXISTS ux_virtual_games_provider_game ON virtual_games (provider_id, game_id);
CREATE UNIQUE INDEX IF NOT EXISTS ux_virtual_games_provider_game
ON virtual_games (provider_id, game_id);
CREATE TABLE IF NOT EXISTS wallets ( CREATE TABLE IF NOT EXISTS wallets (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
balance BIGINT NOT NULL DEFAULT 0, balance BIGINT NOT NULL DEFAULT 0,
@ -325,7 +321,7 @@ CREATE TABLE events (
), ),
default_is_active BOOLEAN NOT NULL DEFAULT true, default_is_active BOOLEAN NOT NULL DEFAULT true,
default_is_featured BOOLEAN NOT NULL DEFAULT false, default_is_featured BOOLEAN NOT NULL DEFAULT false,
default_winning_upper_limit INT NOT NULL, default_winning_upper_limit BIGINT NOT NULL,
is_monitored BOOLEAN NOT NULL DEFAULT FALSE, is_monitored BOOLEAN NOT NULL DEFAULT FALSE,
UNIQUE (id, source) UNIQUE (id, source)
); );
@ -621,7 +617,7 @@ SELECT l.*,
COALESCE(cls.is_featured, l.default_is_featured) AS is_featured, COALESCE(cls.is_featured, l.default_is_featured) AS is_featured,
cls.updated_at cls.updated_at
FROM leagues l FROM leagues l
JOIN company_league_settings cls ON l.id = cls.league_id; LEFT JOIN company_league_settings cls ON l.id = cls.league_id;
CREATE VIEW event_with_settings AS CREATE VIEW event_with_settings AS
SELECT e.*, SELECT e.*,
ces.company_id, ces.company_id,
@ -634,7 +630,7 @@ SELECT e.*,
ces.updated_at, ces.updated_at,
l.country_code as league_cc l.country_code as league_cc
FROM events e FROM events e
JOIN company_event_settings ces ON e.id = ces.event_id LEFT JOIN company_event_settings ces ON e.id = ces.event_id
JOIN leagues l ON l.id = e.league_id; JOIN leagues l ON l.id = e.league_id;
CREATE VIEW event_with_country AS CREATE VIEW event_with_country AS
SELECT events.*, SELECT events.*,
@ -656,7 +652,7 @@ SELECT o.id,
COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds, COALESCE(cos.custom_raw_odds, o.raw_odds) AS raw_odds,
cos.updated_at cos.updated_at
FROM odds_market o FROM odds_market o
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;
CREATE VIEW odds_market_with_event AS CREATE VIEW odds_market_with_event AS
SELECT o.*, SELECT o.*,
e.is_monitored, e.is_monitored,

View File

@ -14,7 +14,8 @@ INSERT INTO events (
start_time, start_time,
is_live, is_live,
status, status,
source source,
default_winning_upper_limit
) )
VALUES ( VALUES (
$1, $1,
@ -31,7 +32,8 @@ VALUES (
$12, $12,
$13, $13,
$14, $14,
$15 $15,
$16
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -44,7 +46,6 @@ SET sport_id = EXCLUDED.sport_id,
away_kit_image = EXCLUDED.away_kit_image, away_kit_image = EXCLUDED.away_kit_image,
league_id = EXCLUDED.league_id, league_id = EXCLUDED.league_id,
league_name = EXCLUDED.league_name, league_name = EXCLUDED.league_name,
league_cc = EXCLUDED.league_cc,
start_time = EXCLUDED.start_time, start_time = EXCLUDED.start_time,
score = EXCLUDED.score, score = EXCLUDED.score,
match_minute = EXCLUDED.match_minute, match_minute = EXCLUDED.match_minute,
@ -53,6 +54,7 @@ SET sport_id = EXCLUDED.sport_id,
match_period = EXCLUDED.match_period, match_period = EXCLUDED.match_period,
is_live = EXCLUDED.is_live, is_live = EXCLUDED.is_live,
source = EXCLUDED.source, source = EXCLUDED.source,
default_winning_upper_limit = EXCLUDED.default_winning_upper_limit,
fetched_at = now(); fetched_at = now();
-- name: SaveEventSettings :exec -- name: SaveEventSettings :exec
INSERT INTO company_event_settings ( INSERT INTO company_event_settings (
@ -152,16 +154,18 @@ ORDER BY start_time ASC
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetTotalCompanyEvents :one -- name: GetTotalCompanyEvents :one
SELECT COUNT(*) SELECT COUNT(*)
FROM event_with_settings FROM events e
WHERE company_id = $1 LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND is_live = false AND ces.company_id = $1
JOIN leagues l ON l.id = e.league_id
WHERE is_live = false
AND status = 'upcoming' AND status = 'upcoming'
AND ( AND (
league_id = sqlc.narg('league_id') league_id = sqlc.narg('league_id')
OR sqlc.narg('league_id') IS NULL OR sqlc.narg('league_id') IS NULL
) )
AND ( AND (
sport_id = sqlc.narg('sport_id') e.sport_id = sqlc.narg('sport_id')
OR sqlc.narg('sport_id') IS NULL OR sqlc.narg('sport_id') IS NULL
) )
AND ( AND (
@ -178,14 +182,29 @@ WHERE company_id = $1
OR sqlc.narg('first_start_time') IS NULL OR sqlc.narg('first_start_time') IS NULL
) )
AND ( AND (
league_cc = sqlc.narg('country_code') l.country_code = sqlc.narg('country_code')
OR sqlc.narg('country_code') IS NULL OR sqlc.narg('country_code') IS NULL
)
AND (
ces.is_featured = sqlc.narg('is_featured')
OR sqlc.narg('is_featured') IS NULL
); );
-- name: GetEventsWithSettings :many -- name: GetEventsWithSettings :many
SELECT * SELECT e.*,
FROM event_with_settings ces.company_id,
WHERE company_id = $1 COALESCE(ces.is_active, e.default_is_active) AS is_active,
AND start_time > now() COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
COALESCE(
ces.winning_upper_limit,
e.default_winning_upper_limit
) AS winning_upper_limit,
ces.updated_at,
l.country_code as league_cc
FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $1
JOIN leagues l ON l.id = e.league_id
WHERE start_time > now()
AND is_live = false AND is_live = false
AND status = 'upcoming' AND status = 'upcoming'
AND ( AND (
@ -193,7 +212,7 @@ WHERE company_id = $1
OR sqlc.narg('league_id') IS NULL OR sqlc.narg('league_id') IS NULL
) )
AND ( AND (
sport_id = sqlc.narg('sport_id') e.sport_id = sqlc.narg('sport_id')
OR sqlc.narg('sport_id') IS NULL OR sqlc.narg('sport_id') IS NULL
) )
AND ( AND (
@ -210,9 +229,12 @@ WHERE company_id = $1
OR sqlc.narg('first_start_time') IS NULL OR sqlc.narg('first_start_time') IS NULL
) )
AND ( AND (
league_cc = sqlc.narg('country_code') l.country_code = sqlc.narg('country_code')
OR sqlc.narg('country_code') IS NULL OR sqlc.narg('country_code') IS NULL
) ) AND (
ces.is_featured = sqlc.narg('is_featured')
OR sqlc.narg('is_featured') IS NULL
)
ORDER BY start_time ASC ORDER BY start_time ASC
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetUpcomingByID :one -- name: GetUpcomingByID :one
@ -223,10 +245,21 @@ WHERE id = $1
AND status = 'upcoming' AND status = 'upcoming'
LIMIT 1; LIMIT 1;
-- name: GetEventWithSettingByID :one -- name: GetEventWithSettingByID :one
SELECT * SELECT e.*,
FROM event_with_settings ces.company_id,
WHERE id = $1 COALESCE(ces.is_active, e.default_is_active) AS is_active,
AND company_id = $2 COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
COALESCE(
ces.winning_upper_limit,
e.default_winning_upper_limit
) AS winning_upper_limit,
ces.updated_at,
l.country_code as league_cc
FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $2
JOIN leagues l ON l.id = e.league_id
WHERE e.id = $1
AND is_live = false AND is_live = false
AND status = 'upcoming' AND status = 'upcoming'
LIMIT 1; LIMIT 1;
@ -243,7 +276,6 @@ WHERE id = $1;
UPDATE events UPDATE events
SET is_monitored = $1 SET is_monitored = $1
WHERE id = $2; WHERE id = $2;
-- name: DeleteEvent :exec -- name: DeleteEvent :exec
DELETE FROM events DELETE FROM events
WHERE id = $1; WHERE id = $1;

View File

@ -43,10 +43,14 @@ WHERE (
ORDER BY name ASC ORDER BY name ASC
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetAllLeaguesWithSettings :many -- name: GetAllLeaguesWithSettings :many
SELECT * SELECT l.*,
FROM league_with_settings cls.company_id,
WHERE (company_id = $1) COALESCE(cls.is_active, l.default_is_active) AS is_active,
AND ( COALESCE(cls.is_featured, l.default_is_featured) AS is_featured,
cls.updated_at
FROM leagues l
LEFT JOIN company_league_settings cls ON l.id = cls.league_id AND company_id = $1
WHERE (
country_code = sqlc.narg('country_code') country_code = sqlc.narg('country_code')
OR sqlc.narg('country_code') IS NULL OR sqlc.narg('country_code') IS NULL
) )
@ -64,7 +68,6 @@ WHERE (company_id = $1)
) )
AND ( AND (
name ILIKE '%' || sqlc.narg('query') || '%' name ILIKE '%' || sqlc.narg('query') || '%'
OR league_name ILIKE '%' || sqlc.narg('query') || '%'
OR sqlc.narg('query') IS NULL OR sqlc.narg('query') IS NULL
) )
ORDER BY is_featured DESC, ORDER BY is_featured DESC,

View File

@ -42,9 +42,22 @@ SELECT *
FROM odds_market_with_event FROM odds_market_with_event
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetAllOddsWithSettings :many -- name: GetAllOddsWithSettings :many
SELECT * SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE company_id = $1 o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetOddByID :one -- name: GetOddByID :one
SELECT * SELECT *
@ -56,16 +69,42 @@ FROM odds_market_with_event
WHERE market_id = $1 WHERE market_id = $1
AND event_id = $2; AND event_id = $2;
-- name: GetOddsWithSettingsByMarketID :one -- name: GetOddsWithSettingsByMarketID :one
SELECT * SELECT o.id,
FROM odds_market_with_settings o.event_id,
o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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 WHERE market_id = $1
AND event_id = $2 AND event_id = $2;
AND company_id = $3;
-- name: GetOddsWithSettingsByID :one -- name: GetOddsWithSettingsByID :one
SELECT * SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE id = $1 o.market_type,
AND company_id = $2; o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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
WHERE o.id = $1;
-- name: GetOddsByEventID :many -- name: GetOddsByEventID :many
SELECT * SELECT *
FROM odds_market_with_event FROM odds_market_with_event
@ -84,10 +123,23 @@ WHERE event_id = $1
) )
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetOddsWithSettingsByEventID :many -- name: GetOddsWithSettingsByEventID :many
SELECT * SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE event_id = $1 o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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 company_id = $2
WHERE event_id = $1
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: DeleteOddsForEvent :exec -- name: DeleteOddsForEvent :exec
DELETE FROM odds_market DELETE FROM odds_market

View File

@ -78,10 +78,21 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]EventWithCountry,
} }
const GetEventWithSettingByID = `-- name: GetEventWithSettingByID :one const GetEventWithSettingByID = `-- name: GetEventWithSettingByID :one
SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, company_id, is_active, is_featured, winning_upper_limit, updated_at, league_cc SELECT e.id, e.sport_id, e.match_name, e.home_team, e.away_team, e.home_team_id, e.away_team_id, e.home_kit_image, e.away_kit_image, e.league_id, e.league_name, e.start_time, e.score, e.match_minute, e.timer_status, e.added_time, e.match_period, e.is_live, e.status, e.fetched_at, e.source, e.default_is_active, e.default_is_featured, e.default_winning_upper_limit, e.is_monitored,
FROM event_with_settings ces.company_id,
WHERE id = $1 COALESCE(ces.is_active, e.default_is_active) AS is_active,
AND company_id = $2 COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
COALESCE(
ces.winning_upper_limit,
e.default_winning_upper_limit
) AS winning_upper_limit,
ces.updated_at,
l.country_code as league_cc
FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $2
JOIN leagues l ON l.id = e.league_id
WHERE e.id = $1
AND is_live = false AND is_live = false
AND status = 'upcoming' AND status = 'upcoming'
LIMIT 1 LIMIT 1
@ -92,9 +103,43 @@ type GetEventWithSettingByIDParams struct {
CompanyID int64 `json:"company_id"` CompanyID int64 `json:"company_id"`
} }
func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithSettingByIDParams) (EventWithSetting, error) { type GetEventWithSettingByIDRow struct {
ID string `json:"id"`
SportID int32 `json:"sport_id"`
MatchName string `json:"match_name"`
HomeTeam string `json:"home_team"`
AwayTeam string `json:"away_team"`
HomeTeamID int64 `json:"home_team_id"`
AwayTeamID int64 `json:"away_team_id"`
HomeKitImage string `json:"home_kit_image"`
AwayKitImage string `json:"away_kit_image"`
LeagueID int64 `json:"league_id"`
LeagueName string `json:"league_name"`
StartTime pgtype.Timestamp `json:"start_time"`
Score pgtype.Text `json:"score"`
MatchMinute pgtype.Int4 `json:"match_minute"`
TimerStatus pgtype.Text `json:"timer_status"`
AddedTime pgtype.Int4 `json:"added_time"`
MatchPeriod pgtype.Int4 `json:"match_period"`
IsLive bool `json:"is_live"`
Status string `json:"status"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
Source string `json:"source"`
DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"`
DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
IsMonitored bool `json:"is_monitored"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
IsFeatured bool `json:"is_featured"`
WinningUpperLimit int32 `json:"winning_upper_limit"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
LeagueCc pgtype.Text `json:"league_cc"`
}
func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithSettingByIDParams) (GetEventWithSettingByIDRow, error) {
row := q.db.QueryRow(ctx, GetEventWithSettingByID, arg.ID, arg.CompanyID) row := q.db.QueryRow(ctx, GetEventWithSettingByID, arg.ID, arg.CompanyID)
var i EventWithSetting var i GetEventWithSettingByIDRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.SportID, &i.SportID,
@ -132,10 +177,21 @@ func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithS
} }
const GetEventsWithSettings = `-- name: GetEventsWithSettings :many const GetEventsWithSettings = `-- name: GetEventsWithSettings :many
SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, company_id, is_active, is_featured, winning_upper_limit, updated_at, league_cc SELECT e.id, e.sport_id, e.match_name, e.home_team, e.away_team, e.home_team_id, e.away_team_id, e.home_kit_image, e.away_kit_image, e.league_id, e.league_name, e.start_time, e.score, e.match_minute, e.timer_status, e.added_time, e.match_period, e.is_live, e.status, e.fetched_at, e.source, e.default_is_active, e.default_is_featured, e.default_winning_upper_limit, e.is_monitored,
FROM event_with_settings ces.company_id,
WHERE company_id = $1 COALESCE(ces.is_active, e.default_is_active) AS is_active,
AND start_time > now() COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
COALESCE(
ces.winning_upper_limit,
e.default_winning_upper_limit
) AS winning_upper_limit,
ces.updated_at,
l.country_code as league_cc
FROM events e
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND ces.company_id = $1
JOIN leagues l ON l.id = e.league_id
WHERE start_time > now()
AND is_live = false AND is_live = false
AND status = 'upcoming' AND status = 'upcoming'
AND ( AND (
@ -143,7 +199,7 @@ WHERE company_id = $1
OR $2 IS NULL OR $2 IS NULL
) )
AND ( AND (
sport_id = $3 e.sport_id = $3
OR $3 IS NULL OR $3 IS NULL
) )
AND ( AND (
@ -160,11 +216,14 @@ WHERE company_id = $1
OR $6 IS NULL OR $6 IS NULL
) )
AND ( AND (
league_cc = $7 l.country_code = $7
OR $7 IS NULL OR $7 IS NULL
) ) AND (
ces.is_featured = $8
OR $8 IS NULL
)
ORDER BY start_time ASC ORDER BY start_time ASC
LIMIT $9 OFFSET $8 LIMIT $10 OFFSET $9
` `
type GetEventsWithSettingsParams struct { type GetEventsWithSettingsParams struct {
@ -175,11 +234,46 @@ type GetEventsWithSettingsParams struct {
LastStartTime pgtype.Timestamp `json:"last_start_time"` LastStartTime pgtype.Timestamp `json:"last_start_time"`
FirstStartTime pgtype.Timestamp `json:"first_start_time"` FirstStartTime pgtype.Timestamp `json:"first_start_time"`
CountryCode pgtype.Text `json:"country_code"` CountryCode pgtype.Text `json:"country_code"`
IsFeatured pgtype.Bool `json:"is_featured"`
Offset pgtype.Int4 `json:"offset"` Offset pgtype.Int4 `json:"offset"`
Limit pgtype.Int4 `json:"limit"` Limit pgtype.Int4 `json:"limit"`
} }
func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSettingsParams) ([]EventWithSetting, error) { type GetEventsWithSettingsRow struct {
ID string `json:"id"`
SportID int32 `json:"sport_id"`
MatchName string `json:"match_name"`
HomeTeam string `json:"home_team"`
AwayTeam string `json:"away_team"`
HomeTeamID int64 `json:"home_team_id"`
AwayTeamID int64 `json:"away_team_id"`
HomeKitImage string `json:"home_kit_image"`
AwayKitImage string `json:"away_kit_image"`
LeagueID int64 `json:"league_id"`
LeagueName string `json:"league_name"`
StartTime pgtype.Timestamp `json:"start_time"`
Score pgtype.Text `json:"score"`
MatchMinute pgtype.Int4 `json:"match_minute"`
TimerStatus pgtype.Text `json:"timer_status"`
AddedTime pgtype.Int4 `json:"added_time"`
MatchPeriod pgtype.Int4 `json:"match_period"`
IsLive bool `json:"is_live"`
Status string `json:"status"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
Source string `json:"source"`
DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"`
DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
IsMonitored bool `json:"is_monitored"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
IsFeatured bool `json:"is_featured"`
WinningUpperLimit int32 `json:"winning_upper_limit"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
LeagueCc pgtype.Text `json:"league_cc"`
}
func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSettingsParams) ([]GetEventsWithSettingsRow, error) {
rows, err := q.db.Query(ctx, GetEventsWithSettings, rows, err := q.db.Query(ctx, GetEventsWithSettings,
arg.CompanyID, arg.CompanyID,
arg.LeagueID, arg.LeagueID,
@ -188,6 +282,7 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe
arg.LastStartTime, arg.LastStartTime,
arg.FirstStartTime, arg.FirstStartTime,
arg.CountryCode, arg.CountryCode,
arg.IsFeatured,
arg.Offset, arg.Offset,
arg.Limit, arg.Limit,
) )
@ -195,9 +290,9 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []EventWithSetting var items []GetEventsWithSettingsRow
for rows.Next() { for rows.Next() {
var i EventWithSetting var i GetEventsWithSettingsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.SportID, &i.SportID,
@ -403,16 +498,18 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
const GetTotalCompanyEvents = `-- name: GetTotalCompanyEvents :one const GetTotalCompanyEvents = `-- name: GetTotalCompanyEvents :one
SELECT COUNT(*) SELECT COUNT(*)
FROM event_with_settings FROM events e
WHERE company_id = $1 LEFT JOIN company_event_settings ces ON e.id = ces.event_id
AND is_live = false AND ces.company_id = $1
JOIN leagues l ON l.id = e.league_id
WHERE is_live = false
AND status = 'upcoming' AND status = 'upcoming'
AND ( AND (
league_id = $2 league_id = $2
OR $2 IS NULL OR $2 IS NULL
) )
AND ( AND (
sport_id = $3 e.sport_id = $3
OR $3 IS NULL OR $3 IS NULL
) )
AND ( AND (
@ -429,9 +526,13 @@ WHERE company_id = $1
OR $6 IS NULL OR $6 IS NULL
) )
AND ( AND (
league_cc = $7 l.country_code = $7
OR $7 IS NULL OR $7 IS NULL
) )
AND (
ces.is_featured = $8
OR $8 IS NULL
)
` `
type GetTotalCompanyEventsParams struct { type GetTotalCompanyEventsParams struct {
@ -442,6 +543,7 @@ type GetTotalCompanyEventsParams struct {
LastStartTime pgtype.Timestamp `json:"last_start_time"` LastStartTime pgtype.Timestamp `json:"last_start_time"`
FirstStartTime pgtype.Timestamp `json:"first_start_time"` FirstStartTime pgtype.Timestamp `json:"first_start_time"`
CountryCode pgtype.Text `json:"country_code"` CountryCode pgtype.Text `json:"country_code"`
IsFeatured pgtype.Bool `json:"is_featured"`
} }
func (q *Queries) GetTotalCompanyEvents(ctx context.Context, arg GetTotalCompanyEventsParams) (int64, error) { func (q *Queries) GetTotalCompanyEvents(ctx context.Context, arg GetTotalCompanyEventsParams) (int64, error) {
@ -453,6 +555,7 @@ func (q *Queries) GetTotalCompanyEvents(ctx context.Context, arg GetTotalCompany
arg.LastStartTime, arg.LastStartTime,
arg.FirstStartTime, arg.FirstStartTime,
arg.CountryCode, arg.CountryCode,
arg.IsFeatured,
) )
var count int64 var count int64
err := row.Scan(&count) err := row.Scan(&count)
@ -573,7 +676,8 @@ INSERT INTO events (
start_time, start_time,
is_live, is_live,
status, status,
source source,
default_winning_upper_limit
) )
VALUES ( VALUES (
$1, $1,
@ -590,7 +694,8 @@ VALUES (
$12, $12,
$13, $13,
$14, $14,
$15 $15,
$16
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -603,7 +708,6 @@ SET sport_id = EXCLUDED.sport_id,
away_kit_image = EXCLUDED.away_kit_image, away_kit_image = EXCLUDED.away_kit_image,
league_id = EXCLUDED.league_id, league_id = EXCLUDED.league_id,
league_name = EXCLUDED.league_name, league_name = EXCLUDED.league_name,
league_cc = EXCLUDED.league_cc,
start_time = EXCLUDED.start_time, start_time = EXCLUDED.start_time,
score = EXCLUDED.score, score = EXCLUDED.score,
match_minute = EXCLUDED.match_minute, match_minute = EXCLUDED.match_minute,
@ -612,25 +716,27 @@ SET sport_id = EXCLUDED.sport_id,
match_period = EXCLUDED.match_period, match_period = EXCLUDED.match_period,
is_live = EXCLUDED.is_live, is_live = EXCLUDED.is_live,
source = EXCLUDED.source, source = EXCLUDED.source,
default_winning_upper_limit = EXCLUDED.default_winning_upper_limit,
fetched_at = now() fetched_at = now()
` `
type InsertEventParams struct { type InsertEventParams struct {
ID string `json:"id"` ID string `json:"id"`
SportID int32 `json:"sport_id"` SportID int32 `json:"sport_id"`
MatchName string `json:"match_name"` MatchName string `json:"match_name"`
HomeTeam string `json:"home_team"` HomeTeam string `json:"home_team"`
AwayTeam string `json:"away_team"` AwayTeam string `json:"away_team"`
HomeTeamID int64 `json:"home_team_id"` HomeTeamID int64 `json:"home_team_id"`
AwayTeamID int64 `json:"away_team_id"` AwayTeamID int64 `json:"away_team_id"`
HomeKitImage string `json:"home_kit_image"` HomeKitImage string `json:"home_kit_image"`
AwayKitImage string `json:"away_kit_image"` AwayKitImage string `json:"away_kit_image"`
LeagueID int64 `json:"league_id"` LeagueID int64 `json:"league_id"`
LeagueName string `json:"league_name"` LeagueName string `json:"league_name"`
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
IsLive bool `json:"is_live"` IsLive bool `json:"is_live"`
Status string `json:"status"` Status string `json:"status"`
Source string `json:"source"` Source string `json:"source"`
DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
} }
func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error { func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error {
@ -650,6 +756,7 @@ func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error
arg.IsLive, arg.IsLive,
arg.Status, arg.Status,
arg.Source, arg.Source,
arg.DefaultWinningUpperLimit,
) )
return err return err
} }

View File

@ -96,10 +96,14 @@ func (q *Queries) GetAllLeagues(ctx context.Context, arg GetAllLeaguesParams) ([
} }
const GetAllLeaguesWithSettings = `-- name: GetAllLeaguesWithSettings :many const GetAllLeaguesWithSettings = `-- name: GetAllLeaguesWithSettings :many
SELECT id, name, img_url, country_code, bet365_id, sport_id, default_is_active, default_is_featured, company_id, is_active, is_featured, updated_at SELECT l.id, l.name, l.img_url, l.country_code, l.bet365_id, l.sport_id, l.default_is_active, l.default_is_featured,
FROM league_with_settings cls.company_id,
WHERE (company_id = $1) COALESCE(cls.is_active, l.default_is_active) AS is_active,
AND ( COALESCE(cls.is_featured, l.default_is_featured) AS is_featured,
cls.updated_at
FROM leagues l
LEFT JOIN company_league_settings cls ON l.id = cls.league_id AND company_id = $1
WHERE (
country_code = $2 country_code = $2
OR $2 IS NULL OR $2 IS NULL
) )
@ -117,7 +121,6 @@ WHERE (company_id = $1)
) )
AND ( AND (
name ILIKE '%' || $6 || '%' name ILIKE '%' || $6 || '%'
OR league_name ILIKE '%' || $6 || '%'
OR $6 IS NULL OR $6 IS NULL
) )
ORDER BY is_featured DESC, ORDER BY is_featured DESC,
@ -136,7 +139,22 @@ type GetAllLeaguesWithSettingsParams struct {
Limit pgtype.Int4 `json:"limit"` Limit pgtype.Int4 `json:"limit"`
} }
func (q *Queries) GetAllLeaguesWithSettings(ctx context.Context, arg GetAllLeaguesWithSettingsParams) ([]LeagueWithSetting, error) { type GetAllLeaguesWithSettingsRow struct {
ID int64 `json:"id"`
Name string `json:"name"`
ImgUrl pgtype.Text `json:"img_url"`
CountryCode pgtype.Text `json:"country_code"`
Bet365ID pgtype.Int4 `json:"bet365_id"`
SportID int32 `json:"sport_id"`
DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
IsFeatured bool `json:"is_featured"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetAllLeaguesWithSettings(ctx context.Context, arg GetAllLeaguesWithSettingsParams) ([]GetAllLeaguesWithSettingsRow, error) {
rows, err := q.db.Query(ctx, GetAllLeaguesWithSettings, rows, err := q.db.Query(ctx, GetAllLeaguesWithSettings,
arg.CompanyID, arg.CompanyID,
arg.CountryCode, arg.CountryCode,
@ -151,9 +169,9 @@ func (q *Queries) GetAllLeaguesWithSettings(ctx context.Context, arg GetAllLeagu
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []LeagueWithSetting var items []GetAllLeaguesWithSettingsRow
for rows.Next() { for rows.Next() {
var i LeagueWithSetting var i GetAllLeaguesWithSettingsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.Name, &i.Name,

View File

@ -321,7 +321,7 @@ type Event struct {
Source string `json:"source"` Source string `json:"source"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
DefaultWinningUpperLimit int32 `json:"default_winning_upper_limit"` DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
IsMonitored bool `json:"is_monitored"` IsMonitored bool `json:"is_monitored"`
} }
@ -356,7 +356,7 @@ type EventWithCountry struct {
Source string `json:"source"` Source string `json:"source"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
DefaultWinningUpperLimit int32 `json:"default_winning_upper_limit"` DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
IsMonitored bool `json:"is_monitored"` IsMonitored bool `json:"is_monitored"`
LeagueCc pgtype.Text `json:"league_cc"` LeagueCc pgtype.Text `json:"league_cc"`
} }
@ -385,9 +385,9 @@ type EventWithSetting struct {
Source string `json:"source"` Source string `json:"source"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
DefaultWinningUpperLimit int32 `json:"default_winning_upper_limit"` DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
IsMonitored bool `json:"is_monitored"` IsMonitored bool `json:"is_monitored"`
CompanyID int64 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsFeatured bool `json:"is_featured"` IsFeatured bool `json:"is_featured"`
WinningUpperLimit int32 `json:"winning_upper_limit"` WinningUpperLimit int32 `json:"winning_upper_limit"`
@ -447,7 +447,7 @@ type LeagueWithSetting struct {
SportID int32 `json:"sport_id"` SportID int32 `json:"sport_id"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
CompanyID int64 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
IsFeatured bool `json:"is_featured"` IsFeatured bool `json:"is_featured"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
@ -520,7 +520,7 @@ type OddsMarketWithSetting struct {
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
ExpiresAt pgtype.Timestamp `json:"expires_at"` ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID int64 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
RawOdds []byte `json:"raw_odds"` RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`

View File

@ -68,9 +68,22 @@ func (q *Queries) GetAllOdds(ctx context.Context, arg GetAllOddsParams) ([]OddsM
} }
const GetAllOddsWithSettings = `-- name: GetAllOddsWithSettings :many const GetAllOddsWithSettings = `-- name: GetAllOddsWithSettings :many
SELECT id, event_id, market_type, market_name, market_category, market_id, default_is_active, fetched_at, expires_at, company_id, is_active, raw_odds, updated_at SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE company_id = $1 o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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
LIMIT $3 OFFSET $2 LIMIT $3 OFFSET $2
` `
@ -80,15 +93,31 @@ type GetAllOddsWithSettingsParams struct {
Limit pgtype.Int4 `json:"limit"` Limit pgtype.Int4 `json:"limit"`
} }
func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWithSettingsParams) ([]OddsMarketWithSetting, error) { type GetAllOddsWithSettingsRow struct {
ID int64 `json:"id"`
EventID string `json:"event_id"`
MarketType string `json:"market_type"`
MarketName string `json:"market_name"`
MarketCategory string `json:"market_category"`
MarketID string `json:"market_id"`
DefaultIsActive bool `json:"default_is_active"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWithSettingsParams) ([]GetAllOddsWithSettingsRow, error) {
rows, err := q.db.Query(ctx, GetAllOddsWithSettings, arg.CompanyID, arg.Offset, arg.Limit) rows, err := q.db.Query(ctx, GetAllOddsWithSettings, arg.CompanyID, arg.Offset, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []OddsMarketWithSetting var items []GetAllOddsWithSettingsRow
for rows.Next() { for rows.Next() {
var i OddsMarketWithSetting var i GetAllOddsWithSettingsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.EventID, &i.EventID,
@ -247,10 +276,23 @@ func (q *Queries) GetOddsByMarketID(ctx context.Context, arg GetOddsByMarketIDPa
} }
const GetOddsWithSettingsByEventID = `-- name: GetOddsWithSettingsByEventID :many const GetOddsWithSettingsByEventID = `-- name: GetOddsWithSettingsByEventID :many
SELECT id, event_id, market_type, market_name, market_category, market_id, default_is_active, fetched_at, expires_at, company_id, is_active, raw_odds, updated_at SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE event_id = $1 o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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 company_id = $2
WHERE event_id = $1
LIMIT $4 OFFSET $3 LIMIT $4 OFFSET $3
` `
@ -261,7 +303,23 @@ type GetOddsWithSettingsByEventIDParams struct {
Limit pgtype.Int4 `json:"limit"` Limit pgtype.Int4 `json:"limit"`
} }
func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsWithSettingsByEventIDParams) ([]OddsMarketWithSetting, error) { type GetOddsWithSettingsByEventIDRow struct {
ID int64 `json:"id"`
EventID string `json:"event_id"`
MarketType string `json:"market_type"`
MarketName string `json:"market_name"`
MarketCategory string `json:"market_category"`
MarketID string `json:"market_id"`
DefaultIsActive bool `json:"default_is_active"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsWithSettingsByEventIDParams) ([]GetOddsWithSettingsByEventIDRow, error) {
rows, err := q.db.Query(ctx, GetOddsWithSettingsByEventID, rows, err := q.db.Query(ctx, GetOddsWithSettingsByEventID,
arg.EventID, arg.EventID,
arg.CompanyID, arg.CompanyID,
@ -272,9 +330,9 @@ func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsW
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []OddsMarketWithSetting var items []GetOddsWithSettingsByEventIDRow
for rows.Next() { for rows.Next() {
var i OddsMarketWithSetting var i GetOddsWithSettingsByEventIDRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.EventID, &i.EventID,
@ -301,10 +359,23 @@ func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsW
} }
const GetOddsWithSettingsByID = `-- name: GetOddsWithSettingsByID :one const GetOddsWithSettingsByID = `-- name: GetOddsWithSettingsByID :one
SELECT id, event_id, market_type, market_name, market_category, market_id, default_is_active, fetched_at, expires_at, company_id, is_active, raw_odds, updated_at SELECT o.id,
FROM odds_market_with_settings o.event_id,
WHERE id = $1 o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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 company_id = $2
WHERE o.id = $1
` `
type GetOddsWithSettingsByIDParams struct { type GetOddsWithSettingsByIDParams struct {
@ -312,9 +383,25 @@ type GetOddsWithSettingsByIDParams struct {
CompanyID int64 `json:"company_id"` CompanyID int64 `json:"company_id"`
} }
func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSettingsByIDParams) (OddsMarketWithSetting, error) { type GetOddsWithSettingsByIDRow struct {
ID int64 `json:"id"`
EventID string `json:"event_id"`
MarketType string `json:"market_type"`
MarketName string `json:"market_name"`
MarketCategory string `json:"market_category"`
MarketID string `json:"market_id"`
DefaultIsActive bool `json:"default_is_active"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSettingsByIDParams) (GetOddsWithSettingsByIDRow, error) {
row := q.db.QueryRow(ctx, GetOddsWithSettingsByID, arg.ID, arg.CompanyID) row := q.db.QueryRow(ctx, GetOddsWithSettingsByID, arg.ID, arg.CompanyID)
var i OddsMarketWithSetting var i GetOddsWithSettingsByIDRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.EventID, &i.EventID,
@ -334,11 +421,24 @@ func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSe
} }
const GetOddsWithSettingsByMarketID = `-- name: GetOddsWithSettingsByMarketID :one const GetOddsWithSettingsByMarketID = `-- name: GetOddsWithSettingsByMarketID :one
SELECT id, event_id, market_type, market_name, market_category, market_id, default_is_active, fetched_at, expires_at, company_id, is_active, raw_odds, updated_at SELECT o.id,
FROM odds_market_with_settings o.event_id,
o.market_type,
o.market_name,
o.market_category,
o.market_id,
o.default_is_active,
o.fetched_at,
o.expires_at,
cos.company_id,
COALESCE(cos.is_active, o.default_is_active) AS is_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 WHERE market_id = $1
AND event_id = $2 AND event_id = $2
AND company_id = $3
` `
type GetOddsWithSettingsByMarketIDParams struct { type GetOddsWithSettingsByMarketIDParams struct {
@ -347,9 +447,25 @@ type GetOddsWithSettingsByMarketIDParams struct {
CompanyID int64 `json:"company_id"` CompanyID int64 `json:"company_id"`
} }
func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOddsWithSettingsByMarketIDParams) (OddsMarketWithSetting, error) { type GetOddsWithSettingsByMarketIDRow struct {
ID int64 `json:"id"`
EventID string `json:"event_id"`
MarketType string `json:"market_type"`
MarketName string `json:"market_name"`
MarketCategory string `json:"market_category"`
MarketID string `json:"market_id"`
DefaultIsActive bool `json:"default_is_active"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
ExpiresAt pgtype.Timestamp `json:"expires_at"`
CompanyID pgtype.Int8 `json:"company_id"`
IsActive bool `json:"is_active"`
RawOdds []byte `json:"raw_odds"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOddsWithSettingsByMarketIDParams) (GetOddsWithSettingsByMarketIDRow, error) {
row := q.db.QueryRow(ctx, GetOddsWithSettingsByMarketID, arg.MarketID, arg.EventID, arg.CompanyID) row := q.db.QueryRow(ctx, GetOddsWithSettingsByMarketID, arg.MarketID, arg.EventID, arg.CompanyID)
var i OddsMarketWithSetting var i GetOddsWithSettingsByMarketIDRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.EventID, &i.EventID,

View File

@ -235,6 +235,7 @@ func ConvertDBBetWithOutcomes(bet dbgen.BetWithOutcome) GetBet {
return GetBet{ return GetBet{
ID: bet.ID, ID: bet.ID,
CompanyID: bet.CompanyID,
Amount: Currency(bet.Amount), Amount: Currency(bet.Amount),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: OutcomeStatus(bet.Status), Status: OutcomeStatus(bet.Status),

View File

@ -69,7 +69,7 @@ type BaseEvent struct {
IsMonitored bool IsMonitored bool
DefaultIsFeatured bool DefaultIsFeatured bool
DefaultIsActive bool DefaultIsActive bool
DefaultWinningUpperLimit int32 DefaultWinningUpperLimit int64
Score ValidString Score ValidString
MatchMinute ValidInt MatchMinute ValidInt
TimerStatus ValidString TimerStatus ValidString
@ -97,7 +97,7 @@ type BaseEventRes struct {
IsMonitored bool `json:"is_monitored"` IsMonitored bool `json:"is_monitored"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultWinningUpperLimit int32 `json:"default_winning_upper_limit"` DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
Score string `json:"score"` Score string `json:"score"`
MatchMinute int `json:"match_minute"` MatchMinute int `json:"match_minute"`
TimerStatus string `json:"timer_status"` TimerStatus string `json:"timer_status"`
@ -128,7 +128,7 @@ type EventWithSettings struct {
WinningUpperLimit int32 WinningUpperLimit int32
DefaultIsFeatured bool DefaultIsFeatured bool
DefaultIsActive bool DefaultIsActive bool
DefaultWinningUpperLimit int32 DefaultWinningUpperLimit int64
Score ValidString Score ValidString
MatchMinute ValidInt MatchMinute ValidInt
TimerStatus ValidString TimerStatus ValidString
@ -140,21 +140,22 @@ type EventWithSettings struct {
} }
type CreateEvent struct { type CreateEvent struct {
ID string ID string
SportID int32 SportID int32
MatchName string MatchName string
HomeTeam string HomeTeam string
AwayTeam string AwayTeam string
HomeTeamID int64 HomeTeamID int64
AwayTeamID int64 AwayTeamID int64
HomeTeamImage string HomeTeamImage string
AwayTeamImage string AwayTeamImage string
LeagueID int64 LeagueID int64
LeagueName string LeagueName string
StartTime time.Time StartTime time.Time
IsLive bool IsLive bool
Status EventStatus Status EventStatus
Source EventSource Source EventSource
DefaultWinningUpperLimit int64
} }
type EventWithSettingsRes struct { type EventWithSettingsRes struct {
@ -179,7 +180,7 @@ type EventWithSettingsRes struct {
WinningUpperLimit int32 `json:"winning_upper_limit"` WinningUpperLimit int32 `json:"winning_upper_limit"`
DefaultIsFeatured bool `json:"default_is_featured"` DefaultIsFeatured bool `json:"default_is_featured"`
DefaultIsActive bool `json:"default_is_active"` DefaultIsActive bool `json:"default_is_active"`
DefaultWinningUpperLimit int32 `json:"default_winning_upper_limit"` DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
Score string `json:"score,omitempty"` Score string `json:"score,omitempty"`
MatchMinute int `json:"match_minute,omitempty"` MatchMinute int `json:"match_minute,omitempty"`
TimerStatus string `json:"timer_status,omitempty"` TimerStatus string `json:"timer_status,omitempty"`
@ -279,21 +280,22 @@ func ConvertDBEvents(events []dbgen.EventWithCountry) []BaseEvent {
func ConvertCreateEvent(e CreateEvent) dbgen.InsertEventParams { func ConvertCreateEvent(e CreateEvent) dbgen.InsertEventParams {
return dbgen.InsertEventParams{ return dbgen.InsertEventParams{
ID: e.ID, ID: e.ID,
SportID: e.SportID, SportID: e.SportID,
MatchName: e.MatchName, MatchName: e.MatchName,
HomeTeam: e.HomeTeam, HomeTeam: e.HomeTeam,
AwayTeam: e.AwayTeam, AwayTeam: e.AwayTeam,
HomeTeamID: e.HomeTeamID, HomeTeamID: e.HomeTeamID,
AwayTeamID: e.AwayTeamID, AwayTeamID: e.AwayTeamID,
HomeKitImage: e.HomeTeamImage, HomeKitImage: e.HomeTeamImage,
AwayKitImage: e.AwayTeamImage, AwayKitImage: e.AwayTeamImage,
LeagueID: e.LeagueID, LeagueID: e.LeagueID,
LeagueName: e.LeagueName, LeagueName: e.LeagueName,
StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true}, StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true},
IsLive: e.IsLive, IsLive: e.IsLive,
Status: string(e.Status), Status: string(e.Status),
Source: string(e.Source), Source: string(e.Source),
DefaultWinningUpperLimit: e.DefaultWinningUpperLimit,
} }
} }

View File

@ -148,7 +148,7 @@ func ConvertDBLeagueWithSetting(lws dbgen.LeagueWithSetting) LeagueWithSettings
return LeagueWithSettings{ return LeagueWithSettings{
ID: lws.ID, ID: lws.ID,
Name: lws.Name, Name: lws.Name,
CompanyID: lws.CompanyID, CompanyID: lws.CompanyID.Int64,
CountryCode: ValidString{ CountryCode: ValidString{
Value: lws.CountryCode.String, Value: lws.CountryCode.String,
Valid: lws.CountryCode.Valid, Valid: lws.CountryCode.Valid,

View File

@ -73,7 +73,7 @@ type Notification struct {
RecipientID int64 `json:"recipient_id"` RecipientID int64 `json:"recipient_id"`
Type NotificationType `json:"type"` Type NotificationType `json:"type"`
Level NotificationLevel `json:"level"` Level NotificationLevel `json:"level"`
ErrorSeverity *NotificationErrorSeverity `json:"error_severity"` ErrorSeverity NotificationErrorSeverity `json:"error_severity"`
Reciever NotificationRecieverSide `json:"reciever"` Reciever NotificationRecieverSide `json:"reciever"`
IsRead bool `json:"is_read"` IsRead bool `json:"is_read"`
DeliveryStatus NotificationDeliveryStatus `json:"delivery_status,omitempty"` DeliveryStatus NotificationDeliveryStatus `json:"delivery_status,omitempty"`

View File

@ -27,7 +27,7 @@ type RawOdd struct {
// The Market ID for the json data can be either string / int which is causing problems when UnMarshalling // The Market ID for the json data can be either string / int which is causing problems when UnMarshalling
type OddsMarket struct { type OddsMarket struct {
ID ValidInt64 `json:"id"` ID ValidInt64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Odds []json.RawMessage `json:"odds"` Odds []json.RawMessage `json:"odds"`
Header string `json:"header,omitempty"` Header string `json:"header,omitempty"`

View File

@ -23,6 +23,7 @@ type SettingList struct {
TotalWinningLimit Currency `json:"total_winning_limit"` TotalWinningLimit Currency `json:"total_winning_limit"`
AmountForBetReferral Currency `json:"amount_for_bet_referral"` AmountForBetReferral Currency `json:"amount_for_bet_referral"`
CashbackAmountCap Currency `json:"cashback_amount_cap"` CashbackAmountCap Currency `json:"cashback_amount_cap"`
DefaultWinningLimit int64 `json:"default_winning_limit"`
} }
type SettingListRes struct { type SettingListRes struct {
@ -33,6 +34,7 @@ type SettingListRes struct {
TotalWinningLimit float32 `json:"total_winning_limit"` TotalWinningLimit float32 `json:"total_winning_limit"`
AmountForBetReferral float32 `json:"amount_for_bet_referral"` AmountForBetReferral float32 `json:"amount_for_bet_referral"`
CashbackAmountCap float32 `json:"cashback_amount_cap"` CashbackAmountCap float32 `json:"cashback_amount_cap"`
DefaultWinningLimit int64 `json:"default_winning_limit"`
} }
func ConvertSettingListRes(settings SettingList) SettingListRes { func ConvertSettingListRes(settings SettingList) SettingListRes {
@ -44,6 +46,7 @@ func ConvertSettingListRes(settings SettingList) SettingListRes {
TotalWinningLimit: settings.TotalWinningLimit.Float32(), TotalWinningLimit: settings.TotalWinningLimit.Float32(),
AmountForBetReferral: settings.AmountForBetReferral.Float32(), AmountForBetReferral: settings.AmountForBetReferral.Float32(),
CashbackAmountCap: settings.CashbackAmountCap.Float32(), CashbackAmountCap: settings.CashbackAmountCap.Float32(),
DefaultWinningLimit: settings.DefaultWinningLimit,
} }
} }
@ -55,6 +58,18 @@ type SaveSettingListReq struct {
TotalWinningLimit *float32 `json:"total_winning_limit,omitempty"` TotalWinningLimit *float32 `json:"total_winning_limit,omitempty"`
AmountForBetReferral *float32 `json:"amount_for_bet_referral,omitempty"` AmountForBetReferral *float32 `json:"amount_for_bet_referral,omitempty"`
CashbackAmountCap *float32 `json:"cashback_amount_cap,omitempty"` CashbackAmountCap *float32 `json:"cashback_amount_cap,omitempty"`
DefaultWinningLimit *int64 `json:"default_winning_limit,omitempty"`
}
type ValidSettingList struct {
SMSProvider ValidString
MaxNumberOfOutcomes ValidInt64
BetAmountLimit ValidCurrency
DailyTicketPerIP ValidInt64
TotalWinningLimit ValidCurrency
AmountForBetReferral ValidCurrency
CashbackAmountCap ValidCurrency
DefaultWinningLimit ValidInt64
} }
func ConvertSaveSettingListReq(settings SaveSettingListReq) ValidSettingList { func ConvertSaveSettingListReq(settings SaveSettingListReq) ValidSettingList {
@ -66,19 +81,10 @@ func ConvertSaveSettingListReq(settings SaveSettingListReq) ValidSettingList {
TotalWinningLimit: ConvertFloat32PtrToCurrency(settings.TotalWinningLimit), TotalWinningLimit: ConvertFloat32PtrToCurrency(settings.TotalWinningLimit),
AmountForBetReferral: ConvertFloat32PtrToCurrency(settings.AmountForBetReferral), AmountForBetReferral: ConvertFloat32PtrToCurrency(settings.AmountForBetReferral),
CashbackAmountCap: ConvertFloat32PtrToCurrency(settings.CashbackAmountCap), CashbackAmountCap: ConvertFloat32PtrToCurrency(settings.CashbackAmountCap),
DefaultWinningLimit: ConvertInt64Ptr(settings.DefaultWinningLimit),
} }
} }
type ValidSettingList struct {
SMSProvider ValidString
MaxNumberOfOutcomes ValidInt64
BetAmountLimit ValidCurrency
DailyTicketPerIP ValidInt64
TotalWinningLimit ValidCurrency
AmountForBetReferral ValidCurrency
CashbackAmountCap ValidCurrency
}
// Always make sure to run the validation before converting this // Always make sure to run the validation before converting this
func (vsl *ValidSettingList) ToSettingList() SettingList { func (vsl *ValidSettingList) ToSettingList() SettingList {
return SettingList{ return SettingList{
@ -89,6 +95,7 @@ func (vsl *ValidSettingList) ToSettingList() SettingList {
TotalWinningLimit: Currency(vsl.TotalWinningLimit.Value), TotalWinningLimit: Currency(vsl.TotalWinningLimit.Value),
AmountForBetReferral: Currency(vsl.AmountForBetReferral.Value), AmountForBetReferral: Currency(vsl.AmountForBetReferral.Value),
CashbackAmountCap: Currency(vsl.CashbackAmountCap.Value), CashbackAmountCap: Currency(vsl.CashbackAmountCap.Value),
DefaultWinningLimit: vsl.DefaultWinningLimit.Value,
} }
} }
@ -104,6 +111,7 @@ func (vsl *ValidSettingList) GetInt64SettingsMap() map[string]*ValidInt64 {
return map[string]*ValidInt64{ return map[string]*ValidInt64{
"max_number_of_outcomes": &vsl.MaxNumberOfOutcomes, "max_number_of_outcomes": &vsl.MaxNumberOfOutcomes,
"daily_ticket_limit": &vsl.DailyTicketPerIP, "daily_ticket_limit": &vsl.DailyTicketPerIP,
"default_winning_limit": &vsl.DefaultWinningLimit,
} }
} }

View File

@ -2,12 +2,12 @@ package repository
import ( import (
"context" "context"
"database/sql"
"errors" "errors"
"fmt" "fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers" "github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
@ -19,7 +19,7 @@ func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany)
for { for {
_, err := s.queries.GetCompanyIDUsingSlug(ctx, uniqueSlug) _, err := s.queries.GetCompanyIDUsingSlug(ctx, uniqueSlug)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, pgx.ErrNoRows) {
// slug is unique // slug is unique
break break
} else { } else {

View File

@ -16,7 +16,6 @@ func (s *Store) SaveEvent(ctx context.Context, e domain.CreateEvent) error {
return s.queries.InsertEvent(ctx, domain.ConvertCreateEvent(e)) return s.queries.InsertEvent(ctx, domain.ConvertCreateEvent(e))
} }
func (s *Store) GetLiveEventIDs(ctx context.Context) ([]string, error) { func (s *Store) GetLiveEventIDs(ctx context.Context) ([]string, error) {
return s.queries.ListLiveEvents(ctx) return s.queries.ListLiveEvents(ctx)
} }
@ -86,6 +85,7 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
FirstStartTime: filter.FirstStartTime.ToPG(), FirstStartTime: filter.FirstStartTime.ToPG(),
LastStartTime: filter.LastStartTime.ToPG(), LastStartTime: filter.LastStartTime.ToPG(),
CountryCode: filter.CountryCode.ToPG(), CountryCode: filter.CountryCode.ToPG(),
IsFeatured: filter.Featured.ToPG(),
}) })
if err != nil { if err != nil {
@ -100,13 +100,69 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
FirstStartTime: filter.FirstStartTime.ToPG(), FirstStartTime: filter.FirstStartTime.ToPG(),
LastStartTime: filter.LastStartTime.ToPG(), LastStartTime: filter.LastStartTime.ToPG(),
CountryCode: filter.CountryCode.ToPG(), CountryCode: filter.CountryCode.ToPG(),
IsFeatured: filter.Featured.ToPG(),
}) })
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
numberOfPages := math.Ceil(float64(totalCount) / float64(filter.Limit.Value)) numberOfPages := math.Ceil(float64(totalCount) / float64(filter.Limit.Value))
return domain.ConvertDBEventWithSettings(events), int64(numberOfPages), nil
result := make([]domain.EventWithSettings, len(events))
for i, event := range events {
result[i] = domain.EventWithSettings{
ID: event.ID,
SportID: event.SportID,
MatchName: event.MatchName,
HomeTeam: event.HomeTeam,
AwayTeam: event.AwayTeam,
HomeTeamID: event.HomeTeamID,
AwayTeamID: event.AwayTeamID,
HomeTeamImage: event.HomeKitImage,
AwayTeamImage: event.AwayKitImage,
LeagueID: event.LeagueID,
LeagueName: event.LeagueName,
LeagueCC: domain.ValidString{
Value: event.LeagueCc.String,
Valid: event.LeagueCc.Valid,
},
StartTime: event.StartTime.Time.UTC(),
Source: domain.EventSource(event.Source),
Status: domain.EventStatus(event.Status),
IsFeatured: event.IsFeatured,
IsMonitored: event.IsMonitored,
IsActive: event.IsActive,
DefaultIsFeatured: event.DefaultIsFeatured,
DefaultIsActive: event.DefaultIsActive,
DefaultWinningUpperLimit: event.DefaultWinningUpperLimit,
Score: domain.ValidString{
Value: event.Score.String,
Valid: event.Score.Valid,
},
MatchMinute: domain.ValidInt{
Value: int(event.MatchMinute.Int32),
Valid: event.MatchMinute.Valid,
},
TimerStatus: domain.ValidString{
Value: event.TimerStatus.String,
Valid: event.TimerStatus.Valid,
},
AddedTime: domain.ValidInt{
Value: int(event.AddedTime.Int32),
Valid: event.AddedTime.Valid,
},
MatchPeriod: domain.ValidInt{
Value: int(event.MatchPeriod.Int32),
Valid: event.MatchPeriod.Valid,
},
IsLive: event.IsLive,
UpdatedAt: event.UpdatedAt.Time,
FetchedAt: event.FetchedAt.Time,
}
}
return result, int64(numberOfPages), nil
} }
func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.BaseEvent, error) { func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.BaseEvent, error) {
event, err := s.queries.GetUpcomingByID(ctx, ID) event, err := s.queries.GetUpcomingByID(ctx, ID)
@ -125,7 +181,56 @@ func (s *Store) GetEventWithSettingByID(ctx context.Context, ID string, companyI
return domain.EventWithSettings{}, err return domain.EventWithSettings{}, err
} }
return domain.ConvertDBEventWithSetting(event), nil res := domain.EventWithSettings{
ID: event.ID,
SportID: event.SportID,
MatchName: event.MatchName,
HomeTeam: event.HomeTeam,
AwayTeam: event.AwayTeam,
HomeTeamID: event.HomeTeamID,
AwayTeamID: event.AwayTeamID,
HomeTeamImage: event.HomeKitImage,
AwayTeamImage: event.AwayKitImage,
LeagueID: event.LeagueID,
LeagueName: event.LeagueName,
LeagueCC: domain.ValidString{
Value: event.LeagueCc.String,
Valid: event.LeagueCc.Valid,
},
StartTime: event.StartTime.Time.UTC(),
Source: domain.EventSource(event.Source),
Status: domain.EventStatus(event.Status),
IsFeatured: event.IsFeatured,
IsMonitored: event.IsMonitored,
IsActive: event.IsActive,
DefaultIsFeatured: event.DefaultIsFeatured,
DefaultIsActive: event.DefaultIsActive,
DefaultWinningUpperLimit: event.DefaultWinningUpperLimit,
Score: domain.ValidString{
Value: event.Score.String,
Valid: event.Score.Valid,
},
MatchMinute: domain.ValidInt{
Value: int(event.MatchMinute.Int32),
Valid: event.MatchMinute.Valid,
},
TimerStatus: domain.ValidString{
Value: event.TimerStatus.String,
Valid: event.TimerStatus.Valid,
},
AddedTime: domain.ValidInt{
Value: int(event.AddedTime.Int32),
Valid: event.AddedTime.Valid,
},
MatchPeriod: domain.ValidInt{
Value: int(event.MatchPeriod.Int32),
Valid: event.MatchPeriod.Valid,
},
IsLive: event.IsLive,
UpdatedAt: event.UpdatedAt.Time,
FetchedAt: event.FetchedAt.Time,
}
return res, nil
} }
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error { func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
params := dbgen.UpdateMatchResultParams{ params := dbgen.UpdateMatchResultParams{
@ -173,7 +278,7 @@ func (s *Store) UpdateEventMonitored(ctx context.Context, eventID string, IsMoni
} }
func (s *Store) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error { func (s *Store) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error {
return s.queries.SaveEventSettings(ctx, domain.ConvertUpdateEventSettings(event)); return s.queries.SaveEventSettings(ctx, domain.ConvertUpdateEventSettings(event))
} }
func (s *Store) DeleteEvent(ctx context.Context, eventID string) error { func (s *Store) DeleteEvent(ctx context.Context, eventID string) error {

View File

@ -51,13 +51,39 @@ func (s *Store) GetAllLeaguesByCompany(ctx context.Context, companyID int64, fil
Int32: int32(filter.Offset.Value * filter.Limit.Value), Int32: int32(filter.Offset.Value * filter.Limit.Value),
Valid: filter.Offset.Valid, Valid: filter.Offset.Valid,
}, },
IsFeatured: filter.IsFeatured.ToPG(),
IsActive: filter.IsActive.ToPG(),
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
return domain.ConvertDBLeagueWithSettings(l), nil result := make([]domain.LeagueWithSettings, len(l))
for i, league := range l {
result[i] = domain.LeagueWithSettings{
ID: league.ID,
Name: league.Name,
CompanyID: league.CompanyID.Int64,
CountryCode: domain.ValidString{
Value: league.CountryCode.String,
Valid: league.CountryCode.Valid,
},
Bet365ID: domain.ValidInt32{
Value: league.Bet365ID.Int32,
Valid: league.Bet365ID.Valid,
},
IsActive: league.IsActive,
SportID: league.SportID,
IsFeatured: league.IsFeatured,
UpdatedAt: league.UpdatedAt.Time,
DefaultIsActive: league.DefaultIsActive,
DefaultIsFeatured: league.DefaultIsFeatured,
}
}
return result, nil
} }
func (s *Store) CheckLeagueSupport(ctx context.Context, leagueID int64, companyID int64) (bool, error) { func (s *Store) CheckLeagueSupport(ctx context.Context, leagueID int64, companyID int64) (bool, error) {

View File

@ -39,8 +39,8 @@ func (s *Store) DisconnectWebSocket(recipientID int64) {
func (r *Repository) CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) { func (r *Repository) CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) {
var errorSeverity pgtype.Text var errorSeverity pgtype.Text
if notification.ErrorSeverity != nil { if notification.ErrorSeverity != "" {
errorSeverity.String = string(*notification.ErrorSeverity) errorSeverity.String = string(notification.ErrorSeverity)
errorSeverity.Valid = true errorSeverity.Valid = true
} }
@ -155,10 +155,12 @@ func (r *Repository) ListRecipientIDs(ctx context.Context, receiver domain.Notif
} }
func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification { func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification {
var errorSeverity *domain.NotificationErrorSeverity var errorSeverity domain.NotificationErrorSeverity
if dbNotif.ErrorSeverity.Valid { if dbNotif.ErrorSeverity.Valid {
s := domain.NotificationErrorSeverity(dbNotif.ErrorSeverity.String) errorSeverity = domain.NotificationErrorSeverity(dbNotif.ErrorSeverity.String)
errorSeverity = &s
} else {
errorSeverity = ""
} }
var deliveryChannel domain.DeliveryChannel var deliveryChannel domain.DeliveryChannel
@ -317,8 +319,6 @@ func (s *Store) CountUnreadNotifications(ctx context.Context, userID int64) (int
return count, nil return count, nil
} }
// func (s *Store) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) { // func (s *Store) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) {
// dbNotifications, err := s.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{ // dbNotifications, err := s.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{
// Limit: int32(limit), // Limit: int32(limit),

View File

@ -88,23 +88,46 @@ func (s *Store) GetAllOddsWithSettings(ctx context.Context, companyID int64, fil
return nil, err return nil, err
} }
domainOdds, err := domain.ConvertDBOddMarketWithSettings(odds) // domainOdds, err := domain.ConvertDBOddMarketWithSettings(odds)
// if err != nil {
// return nil, err
// }
if err != nil { result := make([]domain.OddMarketWithSettings, len(odds))
return nil, err for i, o := range odds {
var rawOdds []json.RawMessage
if len(o.RawOdds) > 0 {
if err := json.Unmarshal(o.RawOdds, &rawOdds); err != nil {
return nil, err
}
} else {
rawOdds = []json.RawMessage{} // explicit empty slice
}
result[i] = domain.OddMarketWithSettings{
ID: o.ID,
EventID: o.EventID,
MarketType: o.MarketType,
MarketName: o.MarketName,
MarketCategory: o.MarketCategory,
MarketID: o.MarketID,
RawOdds: rawOdds,
FetchedAt: o.FetchedAt.Time,
ExpiresAt: o.ExpiresAt.Time,
IsActive: o.IsActive,
}
} }
return domainOdds, nil return result, nil
} }
func (s *Store) GetOddByID(ctx context.Context, id int64) (domain.OddMarket, error) { func (s *Store) GetOddByID(ctx context.Context, id int64) (domain.OddMarket, error) {
odd, err := s.queries.GetOddByID(ctx, id) odd, err := s.queries.GetOddByID(ctx, id)
if err != nil { if err != nil {
return domain.OddMarket{}, err return domain.OddMarket{}, err
} }
convertedOdd, err := domain.ConvertDBOddMarket(odd) convertedOdd, err := domain.ConvertDBOddMarket(odd)
if err != nil { if err != nil {
return domain.OddMarket{}, err return domain.OddMarket{}, err
@ -141,18 +164,40 @@ func (s *Store) GetOddsWithSettingsByMarketID(ctx context.Context, marketID stri
return domain.OddMarketWithSettings{}, err return domain.OddMarketWithSettings{}, err
} }
convertedOdd, err := domain.ConvertDBOddMarketWithSetting(odds) // convertedOdd, err := domain.ConvertDBOddMarketWithSetting(odds)
if err != nil { // if err != nil {
return domain.OddMarketWithSettings{}, err // return domain.OddMarketWithSettings{}, err
// }
var rawOdds []json.RawMessage
if len(odds.RawOdds) > 0 {
if err := json.Unmarshal(odds.RawOdds, &rawOdds); err != nil {
return domain.OddMarketWithSettings{}, err
}
} else {
rawOdds = []json.RawMessage{} // explicit empty slice
} }
return convertedOdd, nil
converted := domain.OddMarketWithSettings{
ID: odds.ID,
EventID: odds.EventID,
MarketType: odds.MarketType,
MarketName: odds.MarketName,
MarketCategory: odds.MarketCategory,
MarketID: odds.MarketID,
RawOdds: rawOdds,
FetchedAt: odds.FetchedAt.Time,
ExpiresAt: odds.ExpiresAt.Time,
IsActive: odds.IsActive,
}
return converted, nil
} }
func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID int64) (domain.OddMarketWithSettings, error) { func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID int64) (domain.OddMarketWithSettings, error) {
odds, err := s.queries.GetOddsWithSettingsByID(ctx, dbgen.GetOddsWithSettingsByIDParams{ odds, err := s.queries.GetOddsWithSettingsByID(ctx, dbgen.GetOddsWithSettingsByIDParams{
ID: ID, ID: ID,
CompanyID: companyID, CompanyID: companyID,
}) })
@ -160,12 +205,35 @@ func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID
return domain.OddMarketWithSettings{}, err return domain.OddMarketWithSettings{}, err
} }
convertedOdd, err := domain.ConvertDBOddMarketWithSetting(odds) // convertedOdd, err := domain.ConvertDBOddMarketWithSetting(odds)
if err != nil { // if err != nil {
return domain.OddMarketWithSettings{}, err // return domain.OddMarketWithSettings{}, err
// }
var rawOdds []json.RawMessage
if len(odds.RawOdds) > 0 {
if err := json.Unmarshal(odds.RawOdds, &rawOdds); err != nil {
return domain.OddMarketWithSettings{}, err
}
} else {
rawOdds = []json.RawMessage{} // explicit empty slice
} }
return convertedOdd, nil
converted := domain.OddMarketWithSettings{
ID: odds.ID,
EventID: odds.EventID,
MarketType: odds.MarketType,
MarketName: odds.MarketName,
MarketCategory: odds.MarketCategory,
MarketID: odds.MarketID,
RawOdds: rawOdds,
FetchedAt: odds.FetchedAt.Time,
ExpiresAt: odds.ExpiresAt.Time,
IsActive: odds.IsActive,
}
return converted, nil
} }
func (s *Store) GetOddsByEventID(ctx context.Context, upcomingID string, filter domain.OddMarketWithEventFilter) ([]domain.OddMarket, error) { func (s *Store) GetOddsByEventID(ctx context.Context, upcomingID string, filter domain.OddMarketWithEventFilter) ([]domain.OddMarket, error) {
@ -208,12 +276,37 @@ func (s *Store) GetOddsWithSettingsByEventID(ctx context.Context, upcomingID str
} }
// Map the results to domain.Odd // Map the results to domain.Odd
domainOdds, err := domain.ConvertDBOddMarketWithSettings(odds) // domainOdds, err := domain.ConvertDBOddMarketWithSettings(odds)
if err != nil { // if err != nil {
return nil, err // return nil, err
// }
result := make([]domain.OddMarketWithSettings, len(odds))
for i, o := range odds {
var rawOdds []json.RawMessage
if len(o.RawOdds) > 0 {
if err := json.Unmarshal(o.RawOdds, &rawOdds); err != nil {
return nil, err
}
} else {
rawOdds = []json.RawMessage{} // explicit empty slice
}
result[i] = domain.OddMarketWithSettings{
ID: o.ID,
EventID: o.EventID,
MarketType: o.MarketType,
MarketName: o.MarketName,
MarketCategory: o.MarketCategory,
MarketID: o.MarketID,
RawOdds: rawOdds,
FetchedAt: o.FetchedAt.Time,
ExpiresAt: o.ExpiresAt.Time,
IsActive: o.IsActive,
}
} }
return domainOdds, nil return result, nil
} }
func (s *Store) DeleteOddsForEvent(ctx context.Context, eventID string) error { func (s *Store) DeleteOddsForEvent(ctx context.Context, eventID string) error {

View File

@ -2,6 +2,7 @@ package repository
import ( import (
"context" "context"
"fmt"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
@ -104,8 +105,10 @@ func (s *Store) GetAllShopBet(ctx context.Context, filter domain.ShopBetFilter)
func (s *Store) GetShopBetByID(ctx context.Context, id int64) (domain.ShopBetDetail, error) { func (s *Store) GetShopBetByID(ctx context.Context, id int64) (domain.ShopBetDetail, error) {
bet, err := s.queries.GetShopBetByID(ctx, id) bet, err := s.queries.GetShopBetByID(ctx, id)
if err != nil { if err != nil {
fmt.Printf("GetShopBetByID Repo BetID %d err %v \n", id, err.Error())
return domain.ShopBetDetail{}, err return domain.ShopBetDetail{}, err
} }
return convertDBShopBetDetail(bet), nil return convertDBShopBetDetail(bet), nil
} }

View File

@ -41,6 +41,7 @@ func convertDBTicketOutcomes(ticket dbgen.TicketWithOutcome) domain.GetTicket {
} }
return domain.GetTicket{ return domain.GetTicket{
ID: ticket.ID, ID: ticket.ID,
CompanyID: ticket.CompanyID,
Amount: domain.Currency(ticket.Amount), Amount: domain.Currency(ticket.Amount),
TotalOdds: ticket.TotalOdds, TotalOdds: ticket.TotalOdds,
Outcomes: outcomes, Outcomes: outcomes,

View File

@ -283,8 +283,10 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
) )
return domain.CreateBetRes{}, err return domain.CreateBetRes{}, err
} }
if count >= 2 {
return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice") // TODO: Make this a setting
if role == domain.RoleCustomer && count >= 10 {
return domain.CreateBetRes{}, fmt.Errorf("max user limit for single outcome")
} }
fastCode := helpers.GenerateFastCode() fastCode := helpers.GenerateFastCode()
@ -340,17 +342,20 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
return domain.CreateBetRes{}, err return domain.CreateBetRes{}, err
} }
if branch.BranchManagerID != userID { if role == domain.RoleBranchManager {
s.mongoLogger.Warn("unauthorized branch for branch manager", if branch.BranchManagerID != userID {
zap.Int64("branch_id", *req.BranchID), s.mongoLogger.Warn("unauthorized branch for branch manager",
zap.Error(err), zap.Int64("branch_id", *req.BranchID),
) zap.Error(err),
return domain.CreateBetRes{}, err )
return domain.CreateBetRes{}, err
}
} }
if branch.CompanyID != companyID {
if branch.CompanyID == companyID {
s.mongoLogger.Warn("unauthorized company", s.mongoLogger.Warn("unauthorized company",
zap.Int64("branch_id", *req.BranchID), zap.Int64("branch_id", *req.BranchID),
zap.Int64("branch_company_id", branch.CompanyID),
zap.Int64("company_id", companyID),
zap.Error(err), zap.Error(err),
) )
} }
@ -1073,8 +1078,6 @@ func (s *Service) SendErrorStatusNotification(ctx context.Context, status domain
message = "We have encounter an error with your bet. We will fix it as soon as we can" message = "We have encounter an error with your bet. We will fix it as soon as we can"
} }
errorSeverityLevel := domain.NotificationErrorSeverityFatal
betNotification := &domain.Notification{ betNotification := &domain.Notification{
RecipientID: userID, RecipientID: userID,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
@ -1088,7 +1091,7 @@ func (s *Service) SendErrorStatusNotification(ctx context.Context, status domain
Message: message, Message: message,
}, },
Priority: 1, Priority: 1,
ErrorSeverity: &errorSeverityLevel, ErrorSeverity: domain.NotificationErrorSeverityHigh,
Metadata: fmt.Appendf(nil, `{ Metadata: fmt.Appendf(nil, `{
"status":%v "status":%v
"more": %v "more": %v
@ -1117,9 +1120,8 @@ func (s *Service) SendAdminErrorAlertNotification(ctx context.Context, status do
message = "We have encounter an error with bet. We will fix it as soon as we can" message = "We have encounter an error with bet. We will fix it as soon as we can"
} }
errorSeverity := domain.NotificationErrorSeverityHigh
betNotification := &domain.Notification{ betNotification := &domain.Notification{
ErrorSeverity: &errorSeverity, ErrorSeverity: domain.NotificationErrorSeverityHigh,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
IsRead: false, IsRead: false,
Type: domain.NOTIFICATION_TYPE_BET_RESULT, Type: domain.NOTIFICATION_TYPE_BET_RESULT,
@ -1322,7 +1324,6 @@ func (s *Service) ProcessBetCashback(ctx context.Context) error {
return err return err
} }
for _, bet := range bets { for _, bet := range bets {
shouldProcess := true shouldProcess := true
loseCount := 0 loseCount := 0

View File

@ -14,6 +14,8 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository" "github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/jackc/pgx/v5"
"go.uber.org/zap" "go.uber.org/zap"
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" // "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
) )
@ -21,13 +23,15 @@ import (
type service struct { type service struct {
token string token string
store *repository.Store store *repository.Store
settingSvc settings.Service
mongoLogger *zap.Logger mongoLogger *zap.Logger
} }
func New(token string, store *repository.Store, mongoLogger *zap.Logger) Service { func New(token string, store *repository.Store, settingSvc settings.Service, mongoLogger *zap.Logger) Service {
return &service{ return &service{
token: token, token: token,
store: store, store: store,
settingSvc: settingSvc,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
} }
} }
@ -206,22 +210,31 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
} }
func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_url string, source domain.EventSource) { func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_url string, source domain.EventSource) {
const pageLimit int = 200
sportIDs := []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91}
// sportIDs := []int{1}
settingsList, err := s.settingSvc.GetGlobalSettingList(ctx)
if err != nil {
s.mongoLogger.Error("Failed to fetch event data for page", zap.Error(err))
return
}
const pageLimit int = 1
// sportIDs := []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91}
sportIDs := []int{1}
var skippedLeague []string
var totalEvents = 0
nilAway := 0
for sportIndex, sportID := range sportIDs { for sportIndex, sportID := range sportIDs {
var totalPages int = 1 var totalPages int = 1
var page int = 0 var page int = 0
var count int = 0 var pageCount int = 0
var skippedLeague []string var sportEvents = 0
var totalEvents = 0
logger := s.mongoLogger.With( logger := s.mongoLogger.With(
zap.String("source", string(source)), zap.String("source", string(source)),
zap.Int("sport_id", sportID), zap.Int("sport_id", sportID),
zap.String("sport_name", domain.Sport(sportID).String()), zap.String("sport_name", domain.Sport(sportID).String()),
zap.Int("count", count), zap.Int("count", pageCount),
zap.Int("totalEvents", totalEvents),
zap.Int("Skipped leagues", len(skippedLeague)), zap.Int("Skipped leagues", len(skippedLeague)),
) )
for page <= totalPages { for page <= totalPages {
@ -301,34 +314,33 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
// } // }
event := domain.CreateEvent{ event := domain.CreateEvent{
ID: ev.ID, ID: ev.ID,
SportID: convertInt32(ev.SportID), SportID: convertInt32(ev.SportID),
MatchName: "", HomeTeam: ev.Home.Name,
HomeTeam: ev.Home.Name, AwayTeam: "", // handle nil safely
AwayTeam: "", // handle nil safely HomeTeamID: convertInt64(ev.Home.ID),
HomeTeamID: convertInt64(ev.Home.ID), AwayTeamID: 0,
AwayTeamID: 0, LeagueID: convertInt64(ev.League.ID),
HomeTeamImage: "", LeagueName: ev.League.Name,
AwayTeamImage: "", StartTime: time.Unix(startUnix, 0).UTC(),
LeagueID: convertInt64(ev.League.ID), Source: source,
LeagueName: ev.League.Name, IsLive: false,
StartTime: time.Unix(startUnix, 0).UTC(), Status: domain.STATUS_PENDING,
Source: source, DefaultWinningUpperLimit: settingsList.DefaultWinningLimit,
IsLive: false,
Status: domain.STATUS_PENDING,
} }
if ev.Away != nil { if ev.Away != nil {
dataLogger.Info("event away is empty")
event.AwayTeam = ev.Away.Name event.AwayTeam = ev.Away.Name
event.AwayTeamID = convertInt64(ev.Away.ID) event.AwayTeamID = convertInt64(ev.Away.ID)
event.MatchName = ev.Home.Name + " vs " + ev.Away.Name event.MatchName = ev.Home.Name + " vs " + ev.Away.Name
} else {
nilAway += 1
} }
ok, err := s.CheckAndInsertEventHistory(ctx, event) ok, _ := s.CheckAndInsertEventHistory(ctx, event)
if err != nil { // if err != nil {
dataLogger.Error("failed to check and insert event history", zap.Error(err)) // dataLogger.Error("failed to check and insert event history", zap.Error(err))
} // }
if ok { if ok {
dataLogger.Info("event history has been recorded") dataLogger.Info("event history has been recorded")
@ -338,7 +350,8 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
if err != nil { if err != nil {
dataLogger.Error("failed to save upcoming event", zap.Error(err)) dataLogger.Error("failed to save upcoming event", zap.Error(err))
} }
totalEvents += 1 sportEvents += 1
} }
// log.Printf("⚠️ Skipped leagues %v", len(skippedLeague)) // log.Printf("⚠️ Skipped leagues %v", len(skippedLeague))
@ -346,26 +359,26 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, source_ur
totalPages = data.Pager.Total / data.Pager.PerPage totalPages = data.Pager.Total / data.Pager.PerPage
if count >= pageLimit { if pageCount >= pageLimit {
break break
} }
if page > totalPages { if page > totalPages {
break break
} }
count++ pageCount++
} }
s.mongoLogger.Info(
"Successfully fetched upcoming events",
zap.String("source", string(source)),
zap.Int("totalEvents", totalEvents),
zap.Int("sport_id", sportID),
zap.String("sport_name", domain.Sport(sportID).String()),
zap.Int("page", page),
zap.Int("total_pages", totalPages),
zap.Int("Skipped leagues", len(skippedLeague)),
)
logger.Info("Completed adding sport", zap.Int("number_of_events_in_sport", sportEvents))
totalEvents += sportEvents
} }
s.mongoLogger.Info(
"Successfully fetched upcoming events",
zap.String("source", string(source)),
zap.Int("totalEvents", totalEvents),
zap.Int("Skipped leagues", len(skippedLeague)),
zap.Int("Events with empty away data", nilAway),
)
} }
func (s *service) CheckAndInsertEventHistory(ctx context.Context, event domain.CreateEvent) (bool, error) { func (s *service) CheckAndInsertEventHistory(ctx context.Context, event domain.CreateEvent) (bool, error) {
@ -379,7 +392,9 @@ func (s *service) CheckAndInsertEventHistory(ctx context.Context, event domain.C
) )
if err != nil { if err != nil {
eventLogger.Error("failed to get event is_monitored", zap.Error(err)) if err != pgx.ErrNoRows {
eventLogger.Info("failed to get event is_monitored", zap.Error(err))
}
return false, err return false, err
} }
@ -478,7 +493,7 @@ func (s *service) GetEventsWithSettings(ctx context.Context, companyID int64, fi
return s.store.GetEventsWithSettings(ctx, companyID, filter) return s.store.GetEventsWithSettings(ctx, companyID, filter)
} }
func (s *service) GetEventWithSettingByID(ctx context.Context, ID string, companyID int64) (domain.EventWithSettings, error) { func (s *service) GetEventWithSettingByID(ctx context.Context, ID string, companyID int64) (domain.EventWithSettings, error) {
return s.store.GetEventWithSettingByID(ctx, ID, companyID) return s.store.GetEventWithSettingByID(ctx, ID, companyID)
} }
func (s *service) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error { func (s *service) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error {

View File

@ -334,14 +334,22 @@ func (s *Service) SendNotificationSMS(ctx context.Context, recipientID int64, me
} }
if !user.PhoneVerified { if !user.PhoneVerified {
return fmt.Errorf("Cannot send notification to unverified phone number") return fmt.Errorf("cannot send notification to unverified phone number")
} }
if user.PhoneNumber == "" { if user.PhoneNumber == "" {
return fmt.Errorf("Phone Number is invalid") return fmt.Errorf("phone Number is invalid")
} }
err = s.messengerSvc.SendSMS(ctx, user.PhoneNumber, message, user.CompanyID) err = s.messengerSvc.SendSMS(ctx, user.PhoneNumber, message, user.CompanyID)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.HandleNotification] Failed to send notification SMS",
zap.Int64("recipient_id", recipientID),
zap.String("user_phone_number", user.PhoneNumber),
zap.String("message", message),
zap.Int64("company_id", user.CompanyID.Value),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return err return err
} }
@ -357,14 +365,22 @@ func (s *Service) SendNotificationEmail(ctx context.Context, recipientID int64,
} }
if !user.EmailVerified { if !user.EmailVerified {
return fmt.Errorf("Cannot send notification to unverified email") return fmt.Errorf("cannot send notification to unverified email")
} }
if user.PhoneNumber == "" { if user.Email == "" {
return fmt.Errorf("Email is invalid") return fmt.Errorf("email is invalid")
} }
err = s.messengerSvc.SendEmail(ctx, user.PhoneNumber, message, subject) err = s.messengerSvc.SendEmail(ctx, user.Email, message, subject)
if err != nil { if err != nil {
s.mongoLogger.Error("[NotificationSvc.HandleNotification] Failed to send notification SMS",
zap.Int64("recipient_id", recipientID),
zap.String("user_email", user.Email),
zap.String("message", message),
zap.Int64("company_id", user.CompanyID.Value),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return err return err
} }

View File

@ -541,9 +541,8 @@ func (s *Service) SendAdminResultStatusErrorNotification(
} }
headline, message := buildHeadlineAndMessage(counts) headline, message := buildHeadlineAndMessage(counts)
errorSeverity := domain.NotificationErrorSeverityLow
notification := &domain.Notification{ notification := &domain.Notification{
ErrorSeverity: &errorSeverity, ErrorSeverity: domain.NotificationErrorSeverityHigh,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
IsRead: false, IsRead: false,
Type: domain.NOTIFICATION_TYPE_BET_RESULT, Type: domain.NOTIFICATION_TYPE_BET_RESULT,

View File

@ -52,6 +52,7 @@ func (s *Service) CreateShopBet(ctx context.Context, userID int64, role domain.R
newBet, err := s.betSvc.PlaceBet(ctx, domain.CreateBetReq{ newBet, err := s.betSvc.PlaceBet(ctx, domain.CreateBetReq{
Outcomes: req.Outcomes, Outcomes: req.Outcomes,
Amount: req.Amount, Amount: req.Amount,
BranchID: branchID,
}, userID, role, *companyID) }, userID, role, *companyID)
if err != nil { if err != nil {
@ -94,6 +95,10 @@ func (s *Service) CreateShopBet(ctx context.Context, userID int64, role domain.R
}, },
}) })
if err != nil {
return domain.ShopBet{}, err
}
return s.transactionStore.CreateShopBet(ctx, domain.CreateShopBet{ return s.transactionStore.CreateShopBet(ctx, domain.CreateShopBet{
ShopTransactionID: newTransaction.ID, ShopTransactionID: newTransaction.ID,
CashoutID: cashoutID, CashoutID: cashoutID,

View File

@ -148,7 +148,7 @@ func (s *Service) notifyCashiersForVerification(ctx context.Context, depositID,
Metadata: metadataJSON, Metadata: metadataJSON,
} }
if err := s.notificationStore.SendNotification(ctx, notification); err != nil { if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
s.logger.Error("failed to send verification notification", s.logger.Error("failed to send verification notification",
"cashier_id", cashier.ID, "cashier_id", cashier.ID,
"error", err) "error", err)
@ -199,7 +199,7 @@ func (s *Service) notifyCustomerVerificationResult(ctx context.Context, deposit
Metadata: metadataJSON, Metadata: metadataJSON,
} }
if err := s.notificationStore.SendNotification(ctx, notification); err != nil { if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
s.logger.Error("failed to send deposit result notification", s.logger.Error("failed to send deposit result notification",
"customer_id", deposit.CustomerID, "customer_id", deposit.CustomerID,
"error", err) "error", err)

View File

@ -14,7 +14,6 @@ type Service struct {
walletStore WalletStore walletStore WalletStore
transferStore TransferStore transferStore TransferStore
directDepositStore DirectDepositStore directDepositStore DirectDepositStore
notificationStore notificationservice.NotificationStore
notificationSvc *notificationservice.Service notificationSvc *notificationservice.Service
userSvc *user.Service userSvc *user.Service
mongoLogger *zap.Logger mongoLogger *zap.Logger
@ -26,7 +25,6 @@ func NewService(
walletStore WalletStore, walletStore WalletStore,
transferStore TransferStore, transferStore TransferStore,
directDepositStore DirectDepositStore, directDepositStore DirectDepositStore,
notificationStore notificationservice.NotificationStore,
notificationSvc *notificationservice.Service, notificationSvc *notificationservice.Service,
userSvc *user.Service, userSvc *user.Service,
mongoLogger *zap.Logger, mongoLogger *zap.Logger,
@ -38,7 +36,6 @@ func NewService(
transferStore: transferStore, transferStore: transferStore,
directDepositStore: directDepositStore, directDepositStore: directDepositStore,
// approvalStore: approvalStore, // approvalStore: approvalStore,
notificationStore: notificationStore,
notificationSvc: notificationSvc, notificationSvc: notificationSvc,
userSvc: userSvc, userSvc: userSvc,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,

View File

@ -135,7 +135,7 @@ func (s *Service) SendTransferNotification(ctx context.Context, senderWallet dom
} }
// Sender notifications // Sender notifications
if err := s.notificationStore.SendNotification(ctx, senderNotify); err != nil { if err := s.notificationSvc.SendNotification(ctx, senderNotify); err != nil {
s.logger.Error("failed to send sender notification", s.logger.Error("failed to send sender notification",
"user_id", "", "user_id", "",
"error", err) "error", err)
@ -163,7 +163,7 @@ func (s *Service) SendTransferNotification(ctx context.Context, senderWallet dom
}`, amount, receiverWallet.Balance, receiverWallet.ID)), }`, amount, receiverWallet.Balance, receiverWallet.ID)),
} }
// Sender notifications // Sender notifications
if err := s.notificationStore.SendNotification(ctx, receiverNotify); err != nil { if err := s.notificationSvc.SendNotification(ctx, receiverNotify); err != nil {
s.logger.Error("failed to send sender notification", s.logger.Error("failed to send sender notification",
"user_id", "", "user_id", "",
"error", err) "error", err)

View File

@ -304,10 +304,10 @@ func (s *Service) GetAdminNotificationRecipients(ctx context.Context, walletID i
} }
func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWallet domain.Wallet) error { func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWallet domain.Wallet) error {
errorSeverity := domain.NotificationErrorSeverityLow
// Send notification to admin team // Send notification to admin team
adminNotification := &domain.Notification{ adminNotification := &domain.Notification{
ErrorSeverity: &errorSeverity, ErrorSeverity: "low",
IsRead: false, IsRead: false,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
RecipientID: adminWallet.UserID, RecipientID: adminWallet.UserID,
@ -343,7 +343,7 @@ func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWalle
for _, adminID := range adminRecipients { for _, adminID := range adminRecipients {
adminNotification.RecipientID = adminID adminNotification.RecipientID = adminID
if err := s.notificationStore.SendNotification(ctx, adminNotification); err != nil { if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
s.mongoLogger.Error("failed to send admin notification", s.mongoLogger.Error("failed to send admin notification",
zap.Int64("admin_id", adminID), zap.Int64("admin_id", adminID),
zap.Error(err), zap.Error(err),
@ -353,7 +353,7 @@ func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWalle
adminNotification.DeliveryChannel = domain.DeliveryChannelEmail adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
if err := s.notificationStore.SendNotification(ctx, adminNotification); err != nil { if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
s.mongoLogger.Error("failed to send email admin notification", s.mongoLogger.Error("failed to send email admin notification",
zap.Int64("admin_id", adminID), zap.Int64("admin_id", adminID),
zap.Error(err), zap.Error(err),
@ -366,11 +366,9 @@ func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWalle
} }
func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, adminWallet domain.Wallet, amount domain.Currency) error { func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, adminWallet domain.Wallet, amount domain.Currency) error {
errorSeverity := domain.NotificationErrorSeverityLow
// Send notification to admin team // Send notification to admin team
adminNotification := &domain.Notification{ adminNotification := &domain.Notification{
ErrorSeverity: &errorSeverity, ErrorSeverity: domain.NotificationErrorSeverityLow,
IsRead: false, IsRead: false,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
RecipientID: adminWallet.UserID, RecipientID: adminWallet.UserID,
@ -408,7 +406,7 @@ func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, a
} }
for _, adminID := range recipients { for _, adminID := range recipients {
adminNotification.RecipientID = adminID adminNotification.RecipientID = adminID
if err := s.notificationStore.SendNotification(ctx, adminNotification); err != nil { if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
s.mongoLogger.Error("failed to send admin notification", s.mongoLogger.Error("failed to send admin notification",
zap.Int64("admin_id", adminID), zap.Int64("admin_id", adminID),
zap.Error(err), zap.Error(err),
@ -417,7 +415,7 @@ func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, a
} }
adminNotification.DeliveryChannel = domain.DeliveryChannelEmail adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
if err := s.notificationStore.SendNotification(ctx, adminNotification); err != nil { if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
s.mongoLogger.Error("failed to send email admin notification", s.mongoLogger.Error("failed to send email admin notification",
zap.Int64("admin_id", adminID), zap.Int64("admin_id", adminID),
zap.Error(err), zap.Error(err),
@ -431,10 +429,9 @@ func (s *Service) SendAdminWalletInsufficientNotification(ctx context.Context, a
} }
func (s *Service) SendCustomerWalletInsufficientNotification(ctx context.Context, customerWallet domain.Wallet, amount domain.Currency) error { func (s *Service) SendCustomerWalletInsufficientNotification(ctx context.Context, customerWallet domain.Wallet, amount domain.Currency) error {
errorSeverity := domain.NotificationErrorSeverityLow
// Send notification to admin team // Send notification to admin team
customerNotification := &domain.Notification{ customerNotification := &domain.Notification{
ErrorSeverity: &errorSeverity, ErrorSeverity: domain.NotificationErrorSeverityLow,
IsRead: false, IsRead: false,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
RecipientID: customerWallet.UserID, RecipientID: customerWallet.UserID,
@ -460,7 +457,7 @@ func (s *Service) SendCustomerWalletInsufficientNotification(ctx context.Context
}`, customerWallet.ID, customerWallet.Balance, amount.Float32()), }`, customerWallet.ID, customerWallet.Balance, amount.Float32()),
} }
if err := s.notificationStore.SendNotification(ctx, customerNotification); err != nil { if err := s.notificationSvc.SendNotification(ctx, customerNotification); err != nil {
s.mongoLogger.Error("failed to create customer notification", s.mongoLogger.Error("failed to create customer notification",
zap.Int64("customer_id", customerWallet.UserID), zap.Int64("customer_id", customerWallet.UserID),
zap.Error(err), zap.Error(err),

View File

@ -7,7 +7,6 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"go.uber.org/zap" "go.uber.org/zap"
@ -46,6 +45,19 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
res, err := h.CreateBetInternal(c, req, userID, role, companyID.Value) res, err := h.CreateBetInternal(c, req, userID, role, companyID.Value)
if err != nil { if err != nil {
switch err {
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, bet.ErrTotalBalanceNotEnough:
h.mongoLoggerSvc.Info("PlaceBet failed",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Int64("userID", userID),
zap.Int64("companyID", companyID.Value),
zap.String("role", string(role)),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
h.mongoLoggerSvc.Error("Failed to create bet", h.mongoLoggerSvc.Error("Failed to create bet",
zap.Int("status_code", fiber.StatusInternalServerError), zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("user_id", userID), zap.Int64("user_id", userID),
@ -200,7 +212,7 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role, companyID) res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role, companyID)
if err != nil { if err != nil {
switch err { switch err {
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, wallet.ErrBalanceInsufficient: case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, bet.ErrTotalBalanceNotEnough:
h.mongoLoggerSvc.Info("PlaceBet failed", h.mongoLoggerSvc.Info("PlaceBet failed",
zap.Int("status_code", fiber.StatusBadRequest), zap.Int("status_code", fiber.StatusBadRequest),
zap.Int64("userID", userID), zap.Int64("userID", userID),

View File

@ -352,6 +352,7 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
Value: true, Value: true,
Valid: true, Valid: true,
}, },
}) })
if err != nil { if err != nil {

View File

@ -208,12 +208,17 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
// return fiber.NewError(fiber.StatusForbidden, "Unauthorized to send notification to this recipient") // return fiber.NewError(fiber.StatusForbidden, "Unauthorized to send notification to this recipient")
// } // }
errorSeverity := domain.NotificationErrorSeverityMedium
if req.ErrorSeverity != nil {
errorSeverity = *req.ErrorSeverity
}
notification := &domain.Notification{ notification := &domain.Notification{
ID: "", ID: "",
RecipientID: req.RecipientID, RecipientID: req.RecipientID,
Type: req.Type, Type: req.Type,
Level: req.Level, Level: req.Level,
ErrorSeverity: req.ErrorSeverity, ErrorSeverity: errorSeverity,
Reciever: req.Reciever, Reciever: req.Reciever,
IsRead: false, IsRead: false,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,
@ -257,12 +262,17 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
notificationIDs := make([]string, 0, len(recipients)) notificationIDs := make([]string, 0, len(recipients))
for _, user := range recipients { for _, user := range recipients {
errorSeverity := domain.NotificationErrorSeverityMedium
if req.ErrorSeverity != nil {
errorSeverity = *req.ErrorSeverity
}
notification := &domain.Notification{ notification := &domain.Notification{
ID: "", ID: "",
RecipientID: user.ID, RecipientID: user.ID,
Type: req.Type, Type: req.Type,
Level: req.Level, Level: req.Level,
ErrorSeverity: req.ErrorSeverity, ErrorSeverity: errorSeverity,
Reciever: req.Reciever, Reciever: req.Reciever,
IsRead: false, IsRead: false,
DeliveryStatus: domain.DeliveryStatusPending, DeliveryStatus: domain.DeliveryStatusPending,

View File

@ -65,7 +65,7 @@ func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
zap.Error(err), zap.Error(err),
zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
) )
return fiber.NewError(statusCode, "failed to create shop bet"+err.Error()) return fiber.NewError(statusCode, err.Error())
} }
res := domain.ConvertShopBet(shopBet) res := domain.ConvertShopBet(shopBet)
@ -464,6 +464,7 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
// role := c.Locals("role").(domain.Role) // role := c.Locals("role").(domain.Role)
companyID := c.Locals("company_id").(domain.ValidInt64) companyID := c.Locals("company_id").(domain.ValidInt64)
branchID := c.Locals("branch_id").(domain.ValidInt64) branchID := c.Locals("branch_id").(domain.ValidInt64)
role := c.Locals("role").(domain.Role)
searchQuery := c.Query("query") searchQuery := c.Query("query")
searchString := domain.ValidString{ searchString := domain.ValidString{
@ -509,6 +510,14 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
} }
} }
companyFilter := int64(c.QueryInt("company_id"))
if role == domain.RoleSuperAdmin {
companyID = domain.ValidInt64{
Value: companyFilter,
Valid: companyFilter != 0,
}
}
// Check user role and fetch transactions accordingly // Check user role and fetch transactions accordingly
transactions, err := h.transactionSvc.GetAllShopTransactions(c.Context(), domain.ShopTransactionFilter{ transactions, err := h.transactionSvc.GetAllShopTransactions(c.Context(), domain.ShopTransactionFilter{
CompanyID: companyID, CompanyID: companyID,

View File

@ -123,6 +123,10 @@ func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
if ticket.CompanyID != companyID.Value { if ticket.CompanyID != companyID.Value {
h.mongoLoggerSvc.Warn("User attempt to access another company ticket", h.mongoLoggerSvc.Warn("User attempt to access another company ticket",
zap.Int64("ticketID", id), zap.Int64("ticketID", id),
zap.Int64("ticket CompanyID", ticket.CompanyID),
zap.Int64("companyID", companyID.Value),
zap.Bool("companyID Valid", companyID.Valid),
zap.Int("status_code", fiber.StatusNotFound), zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err), zap.Error(err),
zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),