Enetpulse fixture and preodds
This commit is contained in:
commit
e429810ebc
18
cmd/main.go
18
cmd/main.go
|
|
@ -41,7 +41,6 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/institutions"
|
||||
issuereporting "github.com/SamuelTariku/FortuneBet-Backend/internal/services/issue_reporting"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/kafka"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/league"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
||||
|
|
@ -122,10 +121,10 @@ func main() {
|
|||
// var userStore user.UserStore
|
||||
|
||||
// Initialize producer
|
||||
topic := "wallet-balance-topic"
|
||||
producer := kafka.NewProducer(cfg.KafkaBrokers, topic)
|
||||
// topic := "wallet-balance-topic"
|
||||
// producer := kafka.NewProducer(cfg.KafkaBrokers, topic)
|
||||
|
||||
notificationSvc := notificationservice.New(notificationRepo, domain.MongoDBLogger, logger, cfg, messengerSvc, userSvc, cfg.KafkaBrokers)
|
||||
notificationSvc := notificationservice.New(notificationRepo, domain.MongoDBLogger, logger, cfg, messengerSvc, userSvc)
|
||||
|
||||
walletSvc := wallet.NewService(
|
||||
wallet.WalletStore(store),
|
||||
|
|
@ -135,7 +134,6 @@ func main() {
|
|||
userSvc,
|
||||
domain.MongoDBLogger,
|
||||
logger,
|
||||
producer,
|
||||
)
|
||||
|
||||
branchSvc := branch.NewService(store)
|
||||
|
|
@ -195,8 +193,8 @@ func main() {
|
|||
store,
|
||||
)
|
||||
|
||||
go httpserver.SetupReportandVirtualGameCronJobs(context.Background(), reportSvc, veliVirtualGameService, "C:/Users/User/Desktop")
|
||||
go httpserver.StartEnetPulseCron(enePulseSvc, domain.MongoDBLogger)
|
||||
go httpserver.SetupReportandVirtualGameCronJobs(context.Background(), reportSvc, veliVirtualGameService, "C:/Users/User/Desktop")
|
||||
go httpserver.ProcessBetCashback(context.TODO(), betSvc)
|
||||
|
||||
bankRepository := repository.NewBankRepository(store)
|
||||
|
|
@ -233,13 +231,13 @@ func main() {
|
|||
fixerFertcherSvc,
|
||||
)
|
||||
|
||||
exchangeWorker := currency.NewExchangeRateWorker(fixerFertcherSvc, logger, cfg)
|
||||
exchangeWorker.Start(context.Background())
|
||||
defer exchangeWorker.Stop()
|
||||
// exchangeWorker := currency.NewExchangeRateWorker(fixerFertcherSvc, logger, cfg)
|
||||
// exchangeWorker.Start(context.Background())
|
||||
// defer exchangeWorker.Stop()
|
||||
go walletMonitorSvc.Start()
|
||||
|
||||
httpserver.StartDataFetchingCrons(eventSvc, *oddsSvc, resultSvc, domain.MongoDBLogger)
|
||||
httpserver.StartTicketCrons(*ticketSvc, domain.MongoDBLogger)
|
||||
httpserver.StartCleanupCrons(*ticketSvc, notificationSvc, domain.MongoDBLogger)
|
||||
|
||||
issueReportingRepo := repository.NewReportedIssueRepository(store)
|
||||
|
||||
|
|
|
|||
221
db/dev_data/betfidel_data.sql
Normal file
221
db/dev_data/betfidel_data.sql
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
DO $$
|
||||
DECLARE _admin_id bigint;
|
||||
_manager_id bigint;
|
||||
_company_wallet_id bigint;
|
||||
_company_id bigint;
|
||||
_branch_id bigint;
|
||||
_branch_wallet_id bigint;
|
||||
_cashier_id bigint;
|
||||
BEGIN
|
||||
INSERT INTO users (
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended
|
||||
)
|
||||
VALUES (
|
||||
'Admin',
|
||||
'BetFidel',
|
||||
'admin.betfidel@gmail.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'admin',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE
|
||||
) ON CONFLICT (email) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _admin_id;
|
||||
INSERT INTO users (
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
'Manager',
|
||||
'BetFidel',
|
||||
'manager.betfidel@gmail.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'branch_manager',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
_company_id
|
||||
) ON CONFLICT (email) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _manager_id;
|
||||
INSERT INTO wallets (
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
_admin_id,
|
||||
'company_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (user_id, type) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _company_wallet_id;
|
||||
INSERT INTO companies (
|
||||
name,
|
||||
slug,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
'FidelBet',
|
||||
'betfidel',
|
||||
_admin_id,
|
||||
_company_wallet_id,
|
||||
0.15,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (slug) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _company_id;
|
||||
UPDATE users
|
||||
SET company_id = _company_id
|
||||
WHERE id = _admin_id;
|
||||
INSERT INTO wallets (
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
_admin_id,
|
||||
'branch_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (user_id, type) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _branch_wallet_id;
|
||||
INSERT INTO branches (
|
||||
name,
|
||||
location,
|
||||
wallet_id,
|
||||
branch_manager_id,
|
||||
company_id,
|
||||
is_self_owned,
|
||||
profit_percent,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
'Test Branch',
|
||||
'addis_ababa',
|
||||
_branch_wallet_id,
|
||||
_manager_id,
|
||||
_company_id,
|
||||
TRUE,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (wallet_id) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _branch_id;
|
||||
INSERT INTO users (
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
'Cashier',
|
||||
'BetFidel',
|
||||
'cashier.betfidel@gmail.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'cashier',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
_company_id
|
||||
) ON CONFLICT (email) DO
|
||||
UPDATE
|
||||
SET updated_at = EXCLUDED.updated_at
|
||||
RETURNING id INTO STRICT _cashier_id;
|
||||
INSERT INTO branch_cashiers (user_id, branch_id)
|
||||
VALUES (_cashier_id, _branch_id);
|
||||
RAISE NOTICE 'BETFIDEL_DEV_DATA (Admin ID: %, Company Wallet ID: %, Company ID: %)',
|
||||
_admin_id,
|
||||
_company_wallet_id,
|
||||
_company_id;
|
||||
RAISE NOTICE 'BETFIDEL_DEV_DATA (Branch ID: %, Branch Wallet ID: %, Manager ID: %)',
|
||||
_branch_id,
|
||||
_branch_wallet_id,
|
||||
_manager_id;
|
||||
RAISE NOTICE 'BETFIDEL_DEV_DATA (Cashier ID: %)',
|
||||
_cashier_id;
|
||||
END $$;
|
||||
|
|
@ -73,10 +73,9 @@ CREATE TABLE IF NOT EXISTS wallets (
|
|||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(user_id, type)
|
||||
UNIQUE(user_id, type),
|
||||
CONSTRAINT balance_positve CHECK (balance >= 0)
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE refresh_tokens (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
|
|
@ -186,19 +185,19 @@ CREATE TABLE IF NOT EXISTS banks (
|
|||
currency VARCHAR(10) NOT NULL,
|
||||
bank_logo TEXT -- URL or base64 string
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS wallets (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
balance BIGINT NOT NULL DEFAULT 0,
|
||||
is_withdraw BOOLEAN NOT NULL,
|
||||
is_bettable BOOLEAN NOT NULL,
|
||||
is_transferable BOOLEAN NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
type VARCHAR(255) NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT balance_positve CHECK (balance >= 0)
|
||||
);
|
||||
-- CREATE TABLE IF NOT EXISTS wallets (
|
||||
-- id BIGSERIAL PRIMARY KEY,
|
||||
-- balance BIGINT NOT NULL DEFAULT 0,
|
||||
-- is_withdraw BOOLEAN NOT NULL,
|
||||
-- is_bettable BOOLEAN NOT NULL,
|
||||
-- is_transferable BOOLEAN NOT NULL,
|
||||
-- user_id BIGINT NOT NULL,
|
||||
-- type VARCHAR(255) NOT NULL,
|
||||
-- is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
-- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
-- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
-- CONSTRAINT balance_positve CHECK (balance >= 0)
|
||||
-- );
|
||||
CREATE TABLE IF NOT EXISTS customer_wallets (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
customer_id BIGINT NOT NULL,
|
||||
|
|
@ -272,7 +271,7 @@ CREATE TABLE IF NOT EXISTS branches (
|
|||
name VARCHAR(255) NOT NULL,
|
||||
location TEXT NOT NULL,
|
||||
profit_percent REAL NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
wallet_id BIGINT NOT NULL,
|
||||
branch_manager_id BIGINT NOT NULL,
|
||||
company_id BIGINT NOT NULL,
|
||||
|
|
@ -321,6 +320,7 @@ CREATE TABLE events (
|
|||
is_live BOOLEAN NOT NULL DEFAULT false,
|
||||
status TEXT NOT NULL,
|
||||
fetched_at TIMESTAMP DEFAULT now (),
|
||||
updated_at TIMESTAMP DEFAULT now (),
|
||||
source TEXT NOT NULL DEFAULT 'b365api' CHECK (
|
||||
source IN ('b365api', 'bfair', '1xbet', 'bwin', 'enetpulse')
|
||||
),
|
||||
|
|
@ -342,7 +342,7 @@ CREATE TABLE company_event_settings (
|
|||
event_id BIGINT NOT NULL,
|
||||
is_active BOOLEAN,
|
||||
is_featured BOOLEAN,
|
||||
winning_upper_limit INT,
|
||||
winning_upper_limit BIGINT,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (company_id, event_id)
|
||||
);
|
||||
|
|
@ -354,6 +354,7 @@ CREATE TABLE odds_market (
|
|||
market_category TEXT NOT NULL,
|
||||
market_id BIGINT NOT NULL,
|
||||
raw_odds JSONB NOT NULL,
|
||||
number_of_outcomes BIGINT NOT NULL,
|
||||
default_is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
fetched_at TIMESTAMP DEFAULT now (),
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
|
|
@ -408,11 +409,11 @@ CREATE TABLE companies (
|
|||
admin_id BIGINT NOT NULL,
|
||||
wallet_id BIGINT NOT NULL,
|
||||
deducted_percentage REAL NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT deducted_percentage_check CHECK (
|
||||
deducted_percentage >= 0
|
||||
deducted_percentage > 0
|
||||
AND deducted_percentage < 1
|
||||
)
|
||||
);
|
||||
|
|
@ -511,6 +512,8 @@ CREATE TABLE IF NOT EXISTS raffles (
|
|||
name VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
-- -1 means there is no limit for the raffle
|
||||
ticket_limit INT NOT NULL DEFAULT -1,
|
||||
type VARCHAR(50) NOT NULL CHECK (type IN ('virtual', 'sport')),
|
||||
status VARCHAR(50) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'completed'))
|
||||
);
|
||||
|
|
@ -580,14 +583,17 @@ CREATE VIEW bet_with_outcomes AS
|
|||
SELECT bets.*,
|
||||
CONCAT (users.first_name, ' ', users.last_name) AS full_name,
|
||||
users.phone_number,
|
||||
JSON_AGG (bet_outcomes.*) AS outcomes
|
||||
JSON_AGG (bet_outcomes.*) AS outcomes,
|
||||
companies.slug as company_slug
|
||||
FROM bets
|
||||
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
|
||||
LEFT JOIN users ON bets.user_id = users.id
|
||||
JOIN companies ON bets.company_id = companies.id
|
||||
GROUP BY bets.id,
|
||||
users.first_name,
|
||||
users.last_name,
|
||||
users.phone_number;
|
||||
users.phone_number,
|
||||
companies.slug;
|
||||
CREATE VIEW ticket_with_outcomes AS
|
||||
SELECT tickets.*,
|
||||
JSON_AGG (ticket_outcomes.*) AS outcomes
|
||||
|
|
@ -644,6 +650,7 @@ SELECT sb.*,
|
|||
st.verified AS transaction_verified,
|
||||
bets.status,
|
||||
bets.total_odds,
|
||||
bets.fast_code,
|
||||
JSON_AGG (bet_outcomes.*) AS outcomes
|
||||
FROM shop_bets AS sb
|
||||
JOIN shop_transactions st ON st.id = sb.shop_transaction_id
|
||||
|
|
@ -657,7 +664,8 @@ GROUP BY sb.id,
|
|||
st.amount,
|
||||
st.verified,
|
||||
bets.status,
|
||||
bets.total_odds;
|
||||
bets.total_odds,
|
||||
bets.fast_code;
|
||||
CREATE VIEW shop_deposit_detail AS
|
||||
SELECT sd.*,
|
||||
st.full_name,
|
||||
|
|
@ -685,16 +693,30 @@ SELECT e.*,
|
|||
ces.winning_upper_limit,
|
||||
e.default_winning_upper_limit
|
||||
) AS winning_upper_limit,
|
||||
ces.updated_at,
|
||||
l.country_code as league_cc
|
||||
ces.updated_at as company_updated_at,
|
||||
l.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events e
|
||||
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
|
||||
JOIN leagues l ON l.id = e.league_id;
|
||||
JOIN leagues l ON l.id = e.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = e.id;
|
||||
CREATE VIEW event_with_country AS
|
||||
SELECT events.*,
|
||||
leagues.country_code as league_cc
|
||||
leagues.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events
|
||||
LEFT JOIN leagues ON leagues.id = events.league_id;
|
||||
LEFT JOIN leagues ON leagues.id = events.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = events.id;
|
||||
CREATE VIEW odds_market_with_settings AS
|
||||
SELECT o.id,
|
||||
o.event_id,
|
||||
|
|
@ -702,6 +724,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ CREATE TABLE IF NOT EXISTS notifications (
|
|||
priority INTEGER,
|
||||
version INTEGER NOT NULL DEFAULT 0,
|
||||
timestamp TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
img TEXT,
|
||||
expires TIMESTAMPTZ NOT NULL,
|
||||
metadata JSONB
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS wallet_threshold_notifications (
|
||||
|
|
|
|||
|
|
@ -3,3 +3,9 @@ DROP TABLE IF EXISTS enetpulse_tournament_templates;
|
|||
DROP TABLE IF EXISTS enetpulse_tournaments;
|
||||
DROP TABLE IF EXISTS enetpulse_tournament_stages;
|
||||
DROP TABLE IF EXISTS enetpulse_fixtures;
|
||||
DROP TABLE IF EXISTS enetpulse_results;
|
||||
DROP TABLE IF EXISTS enetpulse_result_participants;
|
||||
DROP TABLE IF EXISTS enetpulse_result_referees;
|
||||
DROP TABLE IF EXISTS enetpulse_outcome_types;
|
||||
DROP TABLE IF EXISTS enetpulse_preodds;
|
||||
DROP TABLE IF EXISTS enetpulse_preodds_bettingoffers;
|
||||
|
|
@ -133,6 +133,40 @@ SELECT *
|
|||
FROM bet_with_outcomes
|
||||
WHERE status = 2
|
||||
AND processed = false;
|
||||
-- name: GetBetOutcomeViewByEventID :many
|
||||
SELECT bet_outcomes.*,
|
||||
users.first_name,
|
||||
users.last_name,
|
||||
bets.amount,
|
||||
bets.total_odds,
|
||||
companies.name as company_name
|
||||
FROM bet_outcomes
|
||||
JOIN bets ON bets.id = bet_outcomes.bet_id
|
||||
JOIN users ON bets.user_id = users.id
|
||||
JOIN companies ON bets.company_id = companies.id
|
||||
WHERE bet_outcomes.event_id = $1
|
||||
AND (
|
||||
bets.company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
bet_outcomes.status = sqlc.narg('filter_status')
|
||||
OR sqlc.narg('filter_status') IS NULL
|
||||
)
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
-- name: TotalBetOutcomeViewByEventID :one
|
||||
SELECT count(*)
|
||||
FROM bet_outcomes
|
||||
JOIN bets ON bets.id = bet_outcomes.bet_id
|
||||
WHERE bet_outcomes.event_id = $1
|
||||
AND (
|
||||
bets.company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
bet_outcomes.status = sqlc.narg('filter_status')
|
||||
OR sqlc.narg('filter_status') IS NULL
|
||||
);
|
||||
-- name: GetBetOutcomeByEventID :many
|
||||
SELECT *
|
||||
FROM bet_outcomes
|
||||
|
|
@ -180,6 +214,15 @@ UPDATE bet_outcomes
|
|||
SEt status = $1
|
||||
WHERE event_id = $2
|
||||
RETURNING *;
|
||||
-- name: UpdateBetOutcomeStatusForOddID :many
|
||||
UPDATE bet_outcomes
|
||||
SEt status = $1
|
||||
WHERE odd_id = $2
|
||||
RETURNING *;
|
||||
-- name: BulkUpdateBetOutcomeStatusByOddIDs :exec
|
||||
UPDATE bet_outcomes
|
||||
SET status = $1
|
||||
WHERE odd_id = ANY(sqlc.arg('odd_ids')::BIGINT []);
|
||||
-- name: UpdateStatus :exec
|
||||
UPDATE bets
|
||||
SET status = $1,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ wHERE (
|
|||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
|
|
@ -60,6 +64,10 @@ wHERE (
|
|||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
is_shop_bet = sqlc.narg('is_shop_bet')
|
||||
OR sqlc.narg('is_shop_bet') IS NULL
|
||||
|
|
@ -117,6 +125,10 @@ WITH market_counts AS (
|
|||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
|
|
|
|||
|
|
@ -65,7 +65,11 @@ WHERE branch_manager_id = $1;
|
|||
-- name: SearchBranchByName :many
|
||||
SELECT *
|
||||
FROM branch_details
|
||||
WHERE name ILIKE '%' || $1 || '%';
|
||||
WHERE name ILIKE '%' || $1 || '%'
|
||||
AND (
|
||||
company_id = sqlc.narg('company_id')
|
||||
OR sqlc.narg('company_id') IS NULL
|
||||
);
|
||||
-- name: GetAllSupportedOperations :many
|
||||
SELECT *
|
||||
FROM supported_operations;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ INSERT INTO companies (
|
|||
slug,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage
|
||||
deducted_percentage,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *;
|
||||
-- name: GetAllCompanies :many
|
||||
SELECT *
|
||||
|
|
@ -30,15 +31,15 @@ WHERE (
|
|||
SELECT *
|
||||
FROM companies_details
|
||||
WHERE id = $1;
|
||||
-- name: GetCompanyIDUsingSlug :one
|
||||
SELECT id
|
||||
-- name: GetCompanyUsingSlug :one
|
||||
SELECT *
|
||||
FROM companies
|
||||
WHERE slug = $1;
|
||||
-- name: SearchCompanyByName :many
|
||||
SELECT *
|
||||
FROM companies_details
|
||||
WHERE name ILIKE '%' || $1 || '%';
|
||||
-- name: UpdateCompany :one
|
||||
-- name: UpdateCompany :exec
|
||||
UPDATE companies
|
||||
SET name = COALESCE(sqlc.narg(name), name),
|
||||
admin_id = COALESCE(sqlc.narg(admin_id), admin_id),
|
||||
|
|
@ -47,9 +48,9 @@ SET name = COALESCE(sqlc.narg(name), name),
|
|||
sqlc.narg(deducted_percentage),
|
||||
deducted_percentage
|
||||
),
|
||||
slug = COALESCE(sqlc.narg(slug), slug),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
WHERE id = $1;
|
||||
-- name: DeleteCompany :exec
|
||||
DELETE FROM companies
|
||||
WHERE id = $1;
|
||||
|
|
@ -107,7 +107,8 @@ INSERT INTO enetpulse_tournament_stages (
|
|||
updates_count,
|
||||
last_updated_at,
|
||||
status
|
||||
) VALUES (
|
||||
)
|
||||
VALUES (
|
||||
$1, -- stage_id
|
||||
$2, -- name
|
||||
$3, -- tournament_fk
|
||||
|
|
@ -120,6 +121,19 @@ INSERT INTO enetpulse_tournament_stages (
|
|||
$10, -- last_updated_at
|
||||
$11 -- status
|
||||
)
|
||||
ON CONFLICT (stage_id) DO UPDATE
|
||||
SET
|
||||
name = EXCLUDED.name,
|
||||
tournament_fk = EXCLUDED.tournament_fk,
|
||||
gender = EXCLUDED.gender,
|
||||
country_fk = EXCLUDED.country_fk,
|
||||
country_name = EXCLUDED.country_name,
|
||||
start_date = EXCLUDED.start_date,
|
||||
end_date = EXCLUDED.end_date,
|
||||
updates_count = EXCLUDED.updates_count,
|
||||
last_updated_at = EXCLUDED.last_updated_at,
|
||||
status = EXCLUDED.status,
|
||||
updated_at = NOW()
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetAllEnetpulseTournamentStages :many
|
||||
|
|
@ -367,6 +381,48 @@ SELECT *
|
|||
FROM enetpulse_preodds_bettingoffers
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- name: GetFixturesWithPreodds :many
|
||||
SELECT
|
||||
f.fixture_id AS id,
|
||||
f.fixture_id AS fixture_id,
|
||||
f.name AS fixture_name,
|
||||
f.sport_fk,
|
||||
f.tournament_fk,
|
||||
f.tournament_template_fk,
|
||||
f.tournament_stage_fk,
|
||||
f.start_date,
|
||||
f.status_type,
|
||||
f.status_desc_fk,
|
||||
f.round_type_fk,
|
||||
f.updates_count AS fixture_updates_count,
|
||||
f.last_updated_at AS fixture_last_updated_at,
|
||||
f.created_at AS fixture_created_at,
|
||||
f.updated_at AS fixture_updated_at,
|
||||
|
||||
-- Preodds fields
|
||||
p.id AS preodds_db_id,
|
||||
p.preodds_id,
|
||||
p.event_fk,
|
||||
p.outcome_type_fk,
|
||||
p.outcome_scope_fk,
|
||||
p.outcome_subtype_fk,
|
||||
p.event_participant_number,
|
||||
p.iparam,
|
||||
p.iparam2,
|
||||
p.dparam,
|
||||
p.dparam2,
|
||||
p.sparam,
|
||||
p.updates_count AS preodds_updates_count,
|
||||
p.last_updated_at AS preodds_last_updated_at,
|
||||
p.created_at AS preodds_created_at,
|
||||
p.updated_at AS preodds_updated_at
|
||||
|
||||
FROM enetpulse_fixtures f
|
||||
LEFT JOIN enetpulse_preodds p
|
||||
ON p.event_fk = f.id
|
||||
ORDER BY f.start_date DESC;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ SET sport_id = EXCLUDED.sport_id,
|
|||
source = EXCLUDED.source,
|
||||
default_winning_upper_limit = EXCLUDED.default_winning_upper_limit,
|
||||
fetched_at = now();
|
||||
-- name: SaveEventSettings :exec
|
||||
-- name: SaveTenantEventSettings :exec
|
||||
INSERT INTO company_event_settings (
|
||||
company_id,
|
||||
event_id,
|
||||
|
|
@ -218,11 +218,18 @@ SELECT e.*,
|
|||
e.default_winning_upper_limit
|
||||
) AS winning_upper_limit,
|
||||
ces.updated_at,
|
||||
l.country_code as league_cc
|
||||
l.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events e
|
||||
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
|
||||
AND ces.company_id = $1
|
||||
JOIN leagues l ON l.id = e.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = e.id
|
||||
WHERE (
|
||||
is_live = sqlc.narg('is_live')
|
||||
OR sqlc.narg('is_live') IS NULL
|
||||
|
|
@ -292,15 +299,24 @@ SELECT e.*,
|
|||
e.default_winning_upper_limit
|
||||
) AS winning_upper_limit,
|
||||
ces.updated_at,
|
||||
l.country_code as league_cc
|
||||
l.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events e
|
||||
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
|
||||
AND ces.company_id = $2
|
||||
JOIN leagues l ON l.id = e.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = e.id
|
||||
WHERE e.id = $1
|
||||
LIMIT 1;
|
||||
-- name: GetSportAndLeagueIDs :one
|
||||
SELECT sport_id, league_id FROM events
|
||||
SELECT sport_id,
|
||||
league_id
|
||||
FROM events
|
||||
WHERE id = $1;
|
||||
-- name: UpdateMatchResult :exec
|
||||
UPDATE events
|
||||
|
|
@ -313,8 +329,22 @@ FROM events
|
|||
WHERE id = $1;
|
||||
-- name: UpdateEventMonitored :exec
|
||||
UPDATE events
|
||||
SET is_monitored = $1
|
||||
SET is_monitored = $1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $2;
|
||||
-- name: UpdateGlobalEventSettings :exec
|
||||
UPDATE events
|
||||
SET default_is_active = COALESCE(sqlc.narg(default_is_active), default_is_active),
|
||||
default_is_featured = COALESCE(
|
||||
sqlc.narg(default_is_featured),
|
||||
default_is_featured
|
||||
),
|
||||
default_winning_upper_limit = COALESCE(
|
||||
sqlc.narg(default_winning_upper_limit),
|
||||
default_winning_upper_limit
|
||||
),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1;
|
||||
-- name: DeleteEvent :exec
|
||||
DELETE FROM events
|
||||
WHERE id = $1;
|
||||
|
|
@ -14,7 +14,7 @@ SET name = EXCLUDED.name,
|
|||
country_code = EXCLUDED.country_code,
|
||||
bet365_id = EXCLUDED.bet365_id,
|
||||
sport_id = EXCLUDED.sport_id;
|
||||
-- name: InsertLeagueSettings :exec
|
||||
-- name: SaveLeagueSettings :exec
|
||||
INSERT INTO company_league_settings (
|
||||
company_id,
|
||||
league_id,
|
||||
|
|
@ -40,8 +40,31 @@ WHERE (
|
|||
name ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR sqlc.narg('query') IS NULL
|
||||
)
|
||||
AND (
|
||||
default_is_active = sqlc.narg('is_active')
|
||||
OR sqlc.narg('is_active') IS NULL
|
||||
)
|
||||
ORDER BY name ASC
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
-- name: GetTotalLeagues :one
|
||||
SELECT COUNT(*)
|
||||
FROM leagues
|
||||
WHERE (
|
||||
country_code = sqlc.narg('country_code')
|
||||
OR sqlc.narg('country_code') IS NULL
|
||||
)
|
||||
AND (
|
||||
sport_id = sqlc.narg('sport_id')
|
||||
OR sqlc.narg('sport_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
name ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR sqlc.narg('query') IS NULL
|
||||
)
|
||||
AND (
|
||||
default_is_active = sqlc.narg('is_active')
|
||||
OR sqlc.narg('is_active') IS NULL
|
||||
);
|
||||
-- name: GetTotalLeaguesWithSettings :one
|
||||
SELECT COUNT(*)
|
||||
FROM leagues l
|
||||
|
|
@ -118,7 +141,7 @@ SET name = COALESCE(sqlc.narg('name'), name),
|
|||
bet365_id = COALESCE(sqlc.narg('bet365_id'), bet365_id),
|
||||
sport_id = COALESCE(sqlc.narg('sport_id'), sport_id)
|
||||
WHERE id = $1;
|
||||
-- name: UpdateLeagueSettings :exec
|
||||
-- name: UpdateCompanyLeagueSettings :exec
|
||||
UPDATE company_league_settings
|
||||
SET is_active = COALESCE(sqlc.narg('is_active'), is_active),
|
||||
is_featured = COALESCE(
|
||||
|
|
@ -127,3 +150,8 @@ SET is_active = COALESCE(sqlc.narg('is_active'), is_active),
|
|||
)
|
||||
WHERE league_id = $1
|
||||
AND company_id = $2;
|
||||
-- name: UpdateGlobalLeagueSettings :exec
|
||||
UPDATE leagues
|
||||
SET default_is_active = COALESCE(sqlc.narg('is_active'), default_is_active),
|
||||
default_is_featured = COALESCE(sqlc.narg('is_featured'), default_is_featured)
|
||||
WHERE id = $1;
|
||||
|
|
@ -12,6 +12,8 @@ INSERT INTO notifications (
|
|||
payload,
|
||||
priority,
|
||||
timestamp,
|
||||
expires,
|
||||
img,
|
||||
metadata
|
||||
)
|
||||
VALUES (
|
||||
|
|
@ -27,7 +29,9 @@ VALUES (
|
|||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
)
|
||||
RETURNING *;
|
||||
-- name: GetNotification :one
|
||||
|
|
@ -89,3 +93,7 @@ SELECT COUNT(*) as total,
|
|||
END
|
||||
) as unread
|
||||
FROM notifications;
|
||||
|
||||
-- name: DeleteOldNotifications :exec
|
||||
DELETE FROM notifications
|
||||
WHERE expires < now();
|
||||
|
|
@ -5,6 +5,7 @@ INSERT INTO odds_market (
|
|||
market_name,
|
||||
market_category,
|
||||
market_id,
|
||||
number_of_outcomes,
|
||||
raw_odds,
|
||||
fetched_at,
|
||||
expires_at
|
||||
|
|
@ -17,13 +18,15 @@ VALUES (
|
|||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8
|
||||
$8,
|
||||
$9
|
||||
) ON CONFLICT (event_id, market_id) DO
|
||||
UPDATE
|
||||
SET market_type = EXCLUDED.market_type,
|
||||
market_name = EXCLUDED.market_name,
|
||||
market_category = EXCLUDED.market_category,
|
||||
raw_odds = EXCLUDED.raw_odds,
|
||||
number_of_outcomes = EXCLUDED.number_of_outcomes,
|
||||
fetched_at = EXCLUDED.fetched_at,
|
||||
expires_at = EXCLUDED.expires_at;
|
||||
-- name: SaveOddSettings :exec
|
||||
|
|
@ -48,6 +51,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -75,6 +79,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -94,6 +99,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -129,6 +135,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -144,3 +151,14 @@ LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
|||
-- name: DeleteOddsForEvent :exec
|
||||
DELETE FROM odds_market
|
||||
Where event_id = $1;
|
||||
-- name: DeleteAllCompanyOddsSetting :exec
|
||||
DELETE FROM company_odd_settings
|
||||
WHERE company_id = $1;
|
||||
-- name: DeleteCompanyOddsSettingByOddMarketID :exec
|
||||
DELETE FROM company_odd_settings
|
||||
WHERE company_id = $1
|
||||
AND odds_market_id = $2;
|
||||
-- name: UpdateGlobalOddsSetting :exec
|
||||
UPDATE odds_market
|
||||
SET default_is_active = COALESCE(sqlc.narg(default_is_active), default_is_active)
|
||||
WHERE id = $1;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
-- name: CreateRaffle :one
|
||||
INSERT INTO raffles (company_id, name, expires_at, type)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
INSERT INTO raffles (company_id, name, expires_at, ticket_limit, type)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetRafflesOfCompany :many
|
||||
|
|
@ -71,3 +71,19 @@ FROM raffle_sport_filters
|
|||
WHERE raffle_id = $1
|
||||
AND sport_id = $2
|
||||
AND league_id = $3;
|
||||
|
||||
-- name: CheckSportRaffleHasFilter :one
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM raffle_sport_filters WHERE raffle_id = $1
|
||||
) AS has_filter;
|
||||
|
||||
-- name: GetRaffleTicketLimit :one
|
||||
SELECT ticket_limit
|
||||
FROM raffles
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: GetRaffleTicketCount :one
|
||||
SELECT COUNT(*)
|
||||
FROM raffle_tickets
|
||||
WHERE raffle_id = $1
|
||||
AND user_id = $2;
|
||||
|
|
|
|||
31
db/scripts/fix_autoincrement_desync.sql
Normal file
31
db/scripts/fix_autoincrement_desync.sql
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
-- For each table with an id sequence
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('users', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM users;
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('wallets', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM wallets;
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('customer_wallets', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM customer_wallets;
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('companies', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM companies;
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('branches', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM branches;
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('supported_operations', 'id'),
|
||||
COALESCE(MAX(id), 1)
|
||||
)
|
||||
FROM supported_operations;
|
||||
|
|
@ -25,7 +25,7 @@ services:
|
|||
image: mongo:7.0.11
|
||||
restart: always
|
||||
ports:
|
||||
- "27017:27017"
|
||||
- "27022:27017"
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: secret
|
||||
|
|
@ -56,47 +56,17 @@ services:
|
|||
]
|
||||
networks:
|
||||
- app
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- app
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:7.5.0
|
||||
container_name: zookeeper
|
||||
ports:
|
||||
- "22181:2181" # remapped host port (Windows-safe)
|
||||
environment:
|
||||
ZOOKEEPER_CLIENT_PORT: 2181
|
||||
ZOOKEEPER_TICK_TIME: 2000
|
||||
networks:
|
||||
- app
|
||||
|
||||
kafka:
|
||||
image: confluentinc/cp-kafka:7.5.0
|
||||
depends_on:
|
||||
- zookeeper
|
||||
environment:
|
||||
KAFKA_BROKER_ID: 1
|
||||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
||||
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,PLAINTEXT_HOST://0.0.0.0:29092
|
||||
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
ports:
|
||||
- "9092:9092"
|
||||
- "29092:29092"
|
||||
networks:
|
||||
- app
|
||||
|
||||
# redis:
|
||||
# image: redis:7-alpine
|
||||
# ports:
|
||||
# - "6379:6379"
|
||||
# networks:
|
||||
# - app
|
||||
# healthcheck:
|
||||
# test: ["CMD", "redis-cli", "ping"]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
|
|
@ -107,15 +77,9 @@ services:
|
|||
environment:
|
||||
- DB_URL=postgresql://root:secret@postgres:5432/gh?sslmode=disable
|
||||
- MONGO_URI=mongodb://root:secret@mongo:27017
|
||||
- REDIS_ADDR=redis:6379
|
||||
- KAFKA_BROKERS=kafka:9092
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
mongo:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- app
|
||||
command: ["/app/bin/web"]
|
||||
|
|
|
|||
2421
docs/docs.go
2421
docs/docs.go
File diff suppressed because it is too large
Load Diff
2421
docs/swagger.json
2421
docs/swagger.json
File diff suppressed because it is too large
Load Diff
1582
docs/swagger.yaml
1582
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -11,6 +11,22 @@ import (
|
|||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const BulkUpdateBetOutcomeStatusByOddIDs = `-- name: BulkUpdateBetOutcomeStatusByOddIDs :exec
|
||||
UPDATE bet_outcomes
|
||||
SET status = $1
|
||||
WHERE odd_id = ANY($2::BIGINT [])
|
||||
`
|
||||
|
||||
type BulkUpdateBetOutcomeStatusByOddIDsParams struct {
|
||||
Status int32 `json:"status"`
|
||||
OddIds []int64 `json:"odd_ids"`
|
||||
}
|
||||
|
||||
func (q *Queries) BulkUpdateBetOutcomeStatusByOddIDs(ctx context.Context, arg BulkUpdateBetOutcomeStatusByOddIDsParams) error {
|
||||
_, err := q.db.Exec(ctx, BulkUpdateBetOutcomeStatusByOddIDs, arg.Status, arg.OddIds)
|
||||
return err
|
||||
}
|
||||
|
||||
const CreateBet = `-- name: CreateBet :one
|
||||
INSERT INTO bets (
|
||||
amount,
|
||||
|
|
@ -104,7 +120,7 @@ func (q *Queries) DeleteBetOutcome(ctx context.Context, betID int64) error {
|
|||
}
|
||||
|
||||
const GetAllBets = `-- name: GetAllBets :many
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes, company_slug
|
||||
FROM bet_with_outcomes
|
||||
wHERE (
|
||||
user_id = $1
|
||||
|
|
@ -192,6 +208,7 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
|||
&i.FullName,
|
||||
&i.PhoneNumber,
|
||||
&i.Outcomes,
|
||||
&i.CompanySlug,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -204,7 +221,7 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
|||
}
|
||||
|
||||
const GetBetByFastCode = `-- name: GetBetByFastCode :one
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes, company_slug
|
||||
FROM bet_with_outcomes
|
||||
WHERE fast_code = $1
|
||||
LIMIT 1
|
||||
|
|
@ -230,12 +247,13 @@ func (q *Queries) GetBetByFastCode(ctx context.Context, fastCode string) (BetWit
|
|||
&i.FullName,
|
||||
&i.PhoneNumber,
|
||||
&i.Outcomes,
|
||||
&i.CompanySlug,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetBetByID = `-- name: GetBetByID :one
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes, company_slug
|
||||
FROM bet_with_outcomes
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -260,12 +278,13 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
|
|||
&i.FullName,
|
||||
&i.PhoneNumber,
|
||||
&i.Outcomes,
|
||||
&i.CompanySlug,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetBetByUserID = `-- name: GetBetByUserID :many
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes, company_slug
|
||||
FROM bet_with_outcomes
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
|
@ -296,6 +315,7 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID int64) ([]BetWithOu
|
|||
&i.FullName,
|
||||
&i.PhoneNumber,
|
||||
&i.Outcomes,
|
||||
&i.CompanySlug,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -448,8 +468,109 @@ func (q *Queries) GetBetOutcomeCountByOddID(ctx context.Context, oddID int64) (i
|
|||
return count, err
|
||||
}
|
||||
|
||||
const GetBetOutcomeViewByEventID = `-- name: GetBetOutcomeViewByEventID :many
|
||||
SELECT bet_outcomes.id, bet_outcomes.bet_id, bet_outcomes.sport_id, bet_outcomes.event_id, bet_outcomes.odd_id, bet_outcomes.home_team_name, bet_outcomes.away_team_name, bet_outcomes.market_id, bet_outcomes.market_name, bet_outcomes.odd, bet_outcomes.odd_name, bet_outcomes.odd_header, bet_outcomes.odd_handicap, bet_outcomes.status, bet_outcomes.expires,
|
||||
users.first_name,
|
||||
users.last_name,
|
||||
bets.amount,
|
||||
bets.total_odds,
|
||||
companies.name as company_name
|
||||
FROM bet_outcomes
|
||||
JOIN bets ON bets.id = bet_outcomes.bet_id
|
||||
JOIN users ON bets.user_id = users.id
|
||||
JOIN companies ON bets.company_id = companies.id
|
||||
WHERE bet_outcomes.event_id = $1
|
||||
AND (
|
||||
bets.company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
bet_outcomes.status = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
LIMIT $5 OFFSET $4
|
||||
`
|
||||
|
||||
type GetBetOutcomeViewByEventIDParams struct {
|
||||
EventID int64 `json:"event_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
FilterStatus pgtype.Int4 `json:"filter_status"`
|
||||
Offset pgtype.Int4 `json:"offset"`
|
||||
Limit pgtype.Int4 `json:"limit"`
|
||||
}
|
||||
|
||||
type GetBetOutcomeViewByEventIDRow struct {
|
||||
ID int64 `json:"id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
SportID int64 `json:"sport_id"`
|
||||
EventID int64 `json:"event_id"`
|
||||
OddID int64 `json:"odd_id"`
|
||||
HomeTeamName string `json:"home_team_name"`
|
||||
AwayTeamName string `json:"away_team_name"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
MarketName string `json:"market_name"`
|
||||
Odd float32 `json:"odd"`
|
||||
OddName string `json:"odd_name"`
|
||||
OddHeader string `json:"odd_header"`
|
||||
OddHandicap string `json:"odd_handicap"`
|
||||
Status int32 `json:"status"`
|
||||
Expires pgtype.Timestamp `json:"expires"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Amount int64 `json:"amount"`
|
||||
TotalOdds float32 `json:"total_odds"`
|
||||
CompanyName string `json:"company_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBetOutcomeViewByEventID(ctx context.Context, arg GetBetOutcomeViewByEventIDParams) ([]GetBetOutcomeViewByEventIDRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetBetOutcomeViewByEventID,
|
||||
arg.EventID,
|
||||
arg.CompanyID,
|
||||
arg.FilterStatus,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetBetOutcomeViewByEventIDRow
|
||||
for rows.Next() {
|
||||
var i GetBetOutcomeViewByEventIDRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.BetID,
|
||||
&i.SportID,
|
||||
&i.EventID,
|
||||
&i.OddID,
|
||||
&i.HomeTeamName,
|
||||
&i.AwayTeamName,
|
||||
&i.MarketID,
|
||||
&i.MarketName,
|
||||
&i.Odd,
|
||||
&i.OddName,
|
||||
&i.OddHeader,
|
||||
&i.OddHandicap,
|
||||
&i.Status,
|
||||
&i.Expires,
|
||||
&i.FirstName,
|
||||
&i.LastName,
|
||||
&i.Amount,
|
||||
&i.TotalOdds,
|
||||
&i.CompanyName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const GetBetsForCashback = `-- name: GetBetsForCashback :many
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes
|
||||
SELECT id, company_id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, processed, created_at, updated_at, full_name, phone_number, outcomes, company_slug
|
||||
FROM bet_with_outcomes
|
||||
WHERE status = 2
|
||||
AND processed = false
|
||||
|
|
@ -481,6 +602,7 @@ func (q *Queries) GetBetsForCashback(ctx context.Context) ([]BetWithOutcome, err
|
|||
&i.FullName,
|
||||
&i.PhoneNumber,
|
||||
&i.Outcomes,
|
||||
&i.CompanySlug,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -557,6 +679,34 @@ func (q *Queries) GetTotalBets(ctx context.Context, arg GetTotalBetsParams) (int
|
|||
return count, err
|
||||
}
|
||||
|
||||
const TotalBetOutcomeViewByEventID = `-- name: TotalBetOutcomeViewByEventID :one
|
||||
SELECT count(*)
|
||||
FROM bet_outcomes
|
||||
JOIN bets ON bets.id = bet_outcomes.bet_id
|
||||
WHERE bet_outcomes.event_id = $1
|
||||
AND (
|
||||
bets.company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
bet_outcomes.status = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type TotalBetOutcomeViewByEventIDParams struct {
|
||||
EventID int64 `json:"event_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
FilterStatus pgtype.Int4 `json:"filter_status"`
|
||||
}
|
||||
|
||||
func (q *Queries) TotalBetOutcomeViewByEventID(ctx context.Context, arg TotalBetOutcomeViewByEventIDParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, TotalBetOutcomeViewByEventID, arg.EventID, arg.CompanyID, arg.FilterStatus)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const UpdateBetOutcomeStatus = `-- name: UpdateBetOutcomeStatus :one
|
||||
UPDATE bet_outcomes
|
||||
SET status = $1
|
||||
|
|
@ -675,6 +825,54 @@ func (q *Queries) UpdateBetOutcomeStatusForEvent(ctx context.Context, arg Update
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const UpdateBetOutcomeStatusForOddID = `-- name: UpdateBetOutcomeStatusForOddID :many
|
||||
UPDATE bet_outcomes
|
||||
SEt status = $1
|
||||
WHERE odd_id = $2
|
||||
RETURNING id, bet_id, sport_id, event_id, odd_id, home_team_name, away_team_name, market_id, market_name, odd, odd_name, odd_header, odd_handicap, status, expires
|
||||
`
|
||||
|
||||
type UpdateBetOutcomeStatusForOddIDParams struct {
|
||||
Status int32 `json:"status"`
|
||||
OddID int64 `json:"odd_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateBetOutcomeStatusForOddID(ctx context.Context, arg UpdateBetOutcomeStatusForOddIDParams) ([]BetOutcome, error) {
|
||||
rows, err := q.db.Query(ctx, UpdateBetOutcomeStatusForOddID, arg.Status, arg.OddID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []BetOutcome
|
||||
for rows.Next() {
|
||||
var i BetOutcome
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.BetID,
|
||||
&i.SportID,
|
||||
&i.EventID,
|
||||
&i.OddID,
|
||||
&i.HomeTeamName,
|
||||
&i.AwayTeamName,
|
||||
&i.MarketID,
|
||||
&i.MarketName,
|
||||
&i.Odd,
|
||||
&i.OddName,
|
||||
&i.OddHeader,
|
||||
&i.OddHandicap,
|
||||
&i.Status,
|
||||
&i.Expires,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const UpdateBetWithCashback = `-- name: UpdateBetWithCashback :exec
|
||||
UPDATE bets
|
||||
SET processed = $1
|
||||
|
|
|
|||
|
|
@ -34,32 +34,37 @@ wHERE (
|
|||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
is_shop_bet = $2
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
cashed_out = $3
|
||||
is_shop_bet = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
full_name ILIKE '%' || $4 || '%'
|
||||
OR phone_number ILIKE '%' || $4 || '%'
|
||||
cashed_out = $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $5
|
||||
full_name ILIKE '%' || $5 || '%'
|
||||
OR phone_number ILIKE '%' || $5 || '%'
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $6
|
||||
created_at > $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $7
|
||||
OR $7 IS NULL
|
||||
)
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY DATE(created_at)
|
||||
`
|
||||
|
||||
type GetBetStatsParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
IsShopBet pgtype.Bool `json:"is_shop_bet"`
|
||||
CashedOut pgtype.Bool `json:"cashed_out"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
|
|
@ -79,6 +84,7 @@ type GetBetStatsRow struct {
|
|||
func (q *Queries) GetBetStats(ctx context.Context, arg GetBetStatsParams) ([]GetBetStatsRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetBetStats,
|
||||
arg.UserID,
|
||||
arg.CompanyID,
|
||||
arg.IsShopBet,
|
||||
arg.CashedOut,
|
||||
arg.Query,
|
||||
|
|
@ -143,17 +149,22 @@ wHERE (
|
|||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $2
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $3
|
||||
created_at > $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetBetSummaryParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
|
@ -168,7 +179,12 @@ type GetBetSummaryRow struct {
|
|||
}
|
||||
|
||||
func (q *Queries) GetBetSummary(ctx context.Context, arg GetBetSummaryParams) (GetBetSummaryRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetBetSummary, arg.UserID, arg.CreatedBefore, arg.CreatedAfter)
|
||||
row := q.db.QueryRow(ctx, GetBetSummary,
|
||||
arg.UserID,
|
||||
arg.CompanyID,
|
||||
arg.CreatedBefore,
|
||||
arg.CreatedAfter,
|
||||
)
|
||||
var i GetBetSummaryRow
|
||||
err := row.Scan(
|
||||
&i.TotalStakes,
|
||||
|
|
@ -198,13 +214,17 @@ WITH market_counts AS (
|
|||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $2
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $3
|
||||
created_at > $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
GROUP BY DATE(b.created_at),
|
||||
bo.market_name
|
||||
)
|
||||
|
|
@ -216,6 +236,7 @@ WHERE rank = 1
|
|||
|
||||
type GetMarketPopularityParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
|
@ -226,7 +247,12 @@ type GetMarketPopularityRow struct {
|
|||
}
|
||||
|
||||
func (q *Queries) GetMarketPopularity(ctx context.Context, arg GetMarketPopularityParams) (GetMarketPopularityRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetMarketPopularity, arg.UserID, arg.CreatedBefore, arg.CreatedAfter)
|
||||
row := q.db.QueryRow(ctx, GetMarketPopularity,
|
||||
arg.UserID,
|
||||
arg.CompanyID,
|
||||
arg.CreatedBefore,
|
||||
arg.CreatedAfter,
|
||||
)
|
||||
var i GetMarketPopularityRow
|
||||
err := row.Scan(&i.Date, &i.MarketName)
|
||||
return i, err
|
||||
|
|
|
|||
|
|
@ -455,10 +455,19 @@ const SearchBranchByName = `-- name: SearchBranchByName :many
|
|||
SELECT id, name, location, profit_percent, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE name ILIKE '%' || $1 || '%'
|
||||
AND (
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) SearchBranchByName(ctx context.Context, dollar_1 pgtype.Text) ([]BranchDetail, error) {
|
||||
rows, err := q.db.Query(ctx, SearchBranchByName, dollar_1)
|
||||
type SearchBranchByNameParams struct {
|
||||
Column1 pgtype.Text `json:"column_1"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SearchBranchByName(ctx context.Context, arg SearchBranchByNameParams) ([]BranchDetail, error) {
|
||||
rows, err := q.db.Query(ctx, SearchBranchByName, arg.Column1, arg.CompanyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ INSERT INTO companies (
|
|||
slug,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage
|
||||
deducted_percentage,
|
||||
is_active
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, name, slug, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at
|
||||
`
|
||||
|
||||
|
|
@ -29,6 +30,7 @@ type CreateCompanyParams struct {
|
|||
AdminID int64 `json:"admin_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCompany(ctx context.Context, arg CreateCompanyParams) (Company, error) {
|
||||
|
|
@ -38,6 +40,7 @@ func (q *Queries) CreateCompany(ctx context.Context, arg CreateCompanyParams) (C
|
|||
arg.AdminID,
|
||||
arg.WalletID,
|
||||
arg.DeductedPercentage,
|
||||
arg.IsActive,
|
||||
)
|
||||
var i Company
|
||||
err := row.Scan(
|
||||
|
|
@ -153,17 +156,27 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
|
|||
return i, err
|
||||
}
|
||||
|
||||
const GetCompanyIDUsingSlug = `-- name: GetCompanyIDUsingSlug :one
|
||||
SELECT id
|
||||
const GetCompanyUsingSlug = `-- name: GetCompanyUsingSlug :one
|
||||
SELECT id, name, slug, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at
|
||||
FROM companies
|
||||
WHERE slug = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetCompanyIDUsingSlug(ctx context.Context, slug string) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetCompanyIDUsingSlug, slug)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
func (q *Queries) GetCompanyUsingSlug(ctx context.Context, slug string) (Company, error) {
|
||||
row := q.db.QueryRow(ctx, GetCompanyUsingSlug, slug)
|
||||
var i Company
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Slug,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const SearchCompanyByName = `-- name: SearchCompanyByName :many
|
||||
|
|
@ -207,7 +220,7 @@ func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text)
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const UpdateCompany = `-- name: UpdateCompany :one
|
||||
const UpdateCompany = `-- name: UpdateCompany :exec
|
||||
UPDATE companies
|
||||
SET name = COALESCE($2, name),
|
||||
admin_id = COALESCE($3, admin_id),
|
||||
|
|
@ -216,9 +229,9 @@ SET name = COALESCE($2, name),
|
|||
$5,
|
||||
deducted_percentage
|
||||
),
|
||||
slug = COALESCE($6, slug),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING id, name, slug, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateCompanyParams struct {
|
||||
|
|
@ -227,27 +240,17 @@ type UpdateCompanyParams struct {
|
|||
AdminID pgtype.Int8 `json:"admin_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
DeductedPercentage pgtype.Float4 `json:"deducted_percentage"`
|
||||
Slug pgtype.Text `json:"slug"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) (Company, error) {
|
||||
row := q.db.QueryRow(ctx, UpdateCompany,
|
||||
func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateCompany,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.AdminID,
|
||||
arg.IsActive,
|
||||
arg.DeductedPercentage,
|
||||
arg.Slug,
|
||||
)
|
||||
var i Company
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Slug,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,7 +643,8 @@ INSERT INTO enetpulse_tournament_stages (
|
|||
updates_count,
|
||||
last_updated_at,
|
||||
status
|
||||
) VALUES (
|
||||
)
|
||||
VALUES (
|
||||
$1, -- stage_id
|
||||
$2, -- name
|
||||
$3, -- tournament_fk
|
||||
|
|
@ -656,6 +657,19 @@ INSERT INTO enetpulse_tournament_stages (
|
|||
$10, -- last_updated_at
|
||||
$11 -- status
|
||||
)
|
||||
ON CONFLICT (stage_id) DO UPDATE
|
||||
SET
|
||||
name = EXCLUDED.name,
|
||||
tournament_fk = EXCLUDED.tournament_fk,
|
||||
gender = EXCLUDED.gender,
|
||||
country_fk = EXCLUDED.country_fk,
|
||||
country_name = EXCLUDED.country_name,
|
||||
start_date = EXCLUDED.start_date,
|
||||
end_date = EXCLUDED.end_date,
|
||||
updates_count = EXCLUDED.updates_count,
|
||||
last_updated_at = EXCLUDED.last_updated_at,
|
||||
status = EXCLUDED.status,
|
||||
updated_at = NOW()
|
||||
RETURNING id, stage_id, name, tournament_fk, gender, country_fk, country_name, start_date, end_date, updates_count, last_updated_at, status, created_at, updated_at
|
||||
`
|
||||
|
||||
|
|
@ -1158,6 +1172,134 @@ func (q *Queries) GetAllEnetpulseTournaments(ctx context.Context) ([]EnetpulseTo
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetFixturesWithPreodds = `-- name: GetFixturesWithPreodds :many
|
||||
SELECT
|
||||
f.fixture_id AS id,
|
||||
f.fixture_id AS fixture_id,
|
||||
f.name AS fixture_name,
|
||||
f.sport_fk,
|
||||
f.tournament_fk,
|
||||
f.tournament_template_fk,
|
||||
f.tournament_stage_fk,
|
||||
f.start_date,
|
||||
f.status_type,
|
||||
f.status_desc_fk,
|
||||
f.round_type_fk,
|
||||
f.updates_count AS fixture_updates_count,
|
||||
f.last_updated_at AS fixture_last_updated_at,
|
||||
f.created_at AS fixture_created_at,
|
||||
f.updated_at AS fixture_updated_at,
|
||||
|
||||
-- Preodds fields
|
||||
p.id AS preodds_db_id,
|
||||
p.preodds_id,
|
||||
p.event_fk,
|
||||
p.outcome_type_fk,
|
||||
p.outcome_scope_fk,
|
||||
p.outcome_subtype_fk,
|
||||
p.event_participant_number,
|
||||
p.iparam,
|
||||
p.iparam2,
|
||||
p.dparam,
|
||||
p.dparam2,
|
||||
p.sparam,
|
||||
p.updates_count AS preodds_updates_count,
|
||||
p.last_updated_at AS preodds_last_updated_at,
|
||||
p.created_at AS preodds_created_at,
|
||||
p.updated_at AS preodds_updated_at
|
||||
|
||||
FROM enetpulse_fixtures f
|
||||
LEFT JOIN enetpulse_preodds p
|
||||
ON p.event_fk = f.id
|
||||
ORDER BY f.start_date DESC
|
||||
`
|
||||
|
||||
type GetFixturesWithPreoddsRow struct {
|
||||
ID string `json:"id"`
|
||||
FixtureID string `json:"fixture_id"`
|
||||
FixtureName string `json:"fixture_name"`
|
||||
SportFk string `json:"sport_fk"`
|
||||
TournamentFk pgtype.Text `json:"tournament_fk"`
|
||||
TournamentTemplateFk pgtype.Text `json:"tournament_template_fk"`
|
||||
TournamentStageFk pgtype.Text `json:"tournament_stage_fk"`
|
||||
StartDate pgtype.Timestamptz `json:"start_date"`
|
||||
StatusType pgtype.Text `json:"status_type"`
|
||||
StatusDescFk pgtype.Text `json:"status_desc_fk"`
|
||||
RoundTypeFk pgtype.Text `json:"round_type_fk"`
|
||||
FixtureUpdatesCount pgtype.Int4 `json:"fixture_updates_count"`
|
||||
FixtureLastUpdatedAt pgtype.Timestamptz `json:"fixture_last_updated_at"`
|
||||
FixtureCreatedAt pgtype.Timestamptz `json:"fixture_created_at"`
|
||||
FixtureUpdatedAt pgtype.Timestamptz `json:"fixture_updated_at"`
|
||||
PreoddsDbID pgtype.Int8 `json:"preodds_db_id"`
|
||||
PreoddsID pgtype.Text `json:"preodds_id"`
|
||||
EventFk pgtype.Int8 `json:"event_fk"`
|
||||
OutcomeTypeFk pgtype.Int4 `json:"outcome_type_fk"`
|
||||
OutcomeScopeFk pgtype.Int4 `json:"outcome_scope_fk"`
|
||||
OutcomeSubtypeFk pgtype.Int4 `json:"outcome_subtype_fk"`
|
||||
EventParticipantNumber pgtype.Int4 `json:"event_participant_number"`
|
||||
Iparam pgtype.Text `json:"iparam"`
|
||||
Iparam2 pgtype.Text `json:"iparam2"`
|
||||
Dparam pgtype.Text `json:"dparam"`
|
||||
Dparam2 pgtype.Text `json:"dparam2"`
|
||||
Sparam pgtype.Text `json:"sparam"`
|
||||
PreoddsUpdatesCount pgtype.Int4 `json:"preodds_updates_count"`
|
||||
PreoddsLastUpdatedAt pgtype.Timestamptz `json:"preodds_last_updated_at"`
|
||||
PreoddsCreatedAt pgtype.Timestamptz `json:"preodds_created_at"`
|
||||
PreoddsUpdatedAt pgtype.Timestamptz `json:"preodds_updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetFixturesWithPreodds(ctx context.Context) ([]GetFixturesWithPreoddsRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetFixturesWithPreodds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetFixturesWithPreoddsRow
|
||||
for rows.Next() {
|
||||
var i GetFixturesWithPreoddsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.FixtureID,
|
||||
&i.FixtureName,
|
||||
&i.SportFk,
|
||||
&i.TournamentFk,
|
||||
&i.TournamentTemplateFk,
|
||||
&i.TournamentStageFk,
|
||||
&i.StartDate,
|
||||
&i.StatusType,
|
||||
&i.StatusDescFk,
|
||||
&i.RoundTypeFk,
|
||||
&i.FixtureUpdatesCount,
|
||||
&i.FixtureLastUpdatedAt,
|
||||
&i.FixtureCreatedAt,
|
||||
&i.FixtureUpdatedAt,
|
||||
&i.PreoddsDbID,
|
||||
&i.PreoddsID,
|
||||
&i.EventFk,
|
||||
&i.OutcomeTypeFk,
|
||||
&i.OutcomeScopeFk,
|
||||
&i.OutcomeSubtypeFk,
|
||||
&i.EventParticipantNumber,
|
||||
&i.Iparam,
|
||||
&i.Iparam2,
|
||||
&i.Dparam,
|
||||
&i.Dparam2,
|
||||
&i.Sparam,
|
||||
&i.PreoddsUpdatesCount,
|
||||
&i.PreoddsLastUpdatedAt,
|
||||
&i.PreoddsCreatedAt,
|
||||
&i.PreoddsUpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const GetTournamentStagesByTournamentFK = `-- name: GetTournamentStagesByTournamentFK :many
|
||||
SELECT id, stage_id, name, tournament_fk, gender, country_fk, country_name, start_date, end_date, updates_count, last_updated_at, status, created_at, updated_at
|
||||
FROM enetpulse_tournament_stages
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func (q *Queries) DeleteEvent(ctx context.Context, id int64) error {
|
|||
}
|
||||
|
||||
const GetAllEvents = `-- name: GetAllEvents :many
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes
|
||||
FROM event_with_country
|
||||
WHERE (
|
||||
is_live = $1
|
||||
|
|
@ -122,12 +122,14 @@ func (q *Queries) GetAllEvents(ctx context.Context, arg GetAllEventsParams) ([]E
|
|||
&i.IsLive,
|
||||
&i.Status,
|
||||
&i.FetchedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Source,
|
||||
&i.DefaultIsActive,
|
||||
&i.DefaultIsFeatured,
|
||||
&i.DefaultWinningUpperLimit,
|
||||
&i.IsMonitored,
|
||||
&i.LeagueCc,
|
||||
&i.TotalOutcomes,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -140,7 +142,7 @@ func (q *Queries) GetAllEvents(ctx context.Context, arg GetAllEventsParams) ([]E
|
|||
}
|
||||
|
||||
const GetEventByID = `-- name: GetEventByID :one
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes
|
||||
FROM event_with_country
|
||||
WHERE id = $1
|
||||
LIMIT 1
|
||||
|
|
@ -171,18 +173,20 @@ func (q *Queries) GetEventByID(ctx context.Context, id int64) (EventWithCountry,
|
|||
&i.IsLive,
|
||||
&i.Status,
|
||||
&i.FetchedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Source,
|
||||
&i.DefaultIsActive,
|
||||
&i.DefaultIsFeatured,
|
||||
&i.DefaultWinningUpperLimit,
|
||||
&i.IsMonitored,
|
||||
&i.LeagueCc,
|
||||
&i.TotalOutcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetEventBySourceID = `-- name: GetEventBySourceID :one
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc
|
||||
SELECT id, source_event_id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, updated_at, source, default_is_active, default_is_featured, default_winning_upper_limit, is_monitored, league_cc, total_outcomes
|
||||
FROM event_with_country
|
||||
WHERE source_event_id = $1
|
||||
AND source = $2
|
||||
|
|
@ -218,18 +222,20 @@ func (q *Queries) GetEventBySourceID(ctx context.Context, arg GetEventBySourceID
|
|||
&i.IsLive,
|
||||
&i.Status,
|
||||
&i.FetchedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Source,
|
||||
&i.DefaultIsActive,
|
||||
&i.DefaultIsFeatured,
|
||||
&i.DefaultWinningUpperLimit,
|
||||
&i.IsMonitored,
|
||||
&i.LeagueCc,
|
||||
&i.TotalOutcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetEventWithSettingByID = `-- name: GetEventWithSettingByID :one
|
||||
SELECT e.id, e.source_event_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,
|
||||
SELECT e.id, e.source_event_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.updated_at, e.source, e.default_is_active, e.default_is_featured, e.default_winning_upper_limit, e.is_monitored,
|
||||
ces.company_id,
|
||||
COALESCE(ces.is_active, e.default_is_active) AS is_active,
|
||||
COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
|
||||
|
|
@ -238,11 +244,18 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te
|
|||
e.default_winning_upper_limit
|
||||
) AS winning_upper_limit,
|
||||
ces.updated_at,
|
||||
l.country_code as league_cc
|
||||
l.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events e
|
||||
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
|
||||
AND ces.company_id = $2
|
||||
JOIN leagues l ON l.id = e.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = e.id
|
||||
WHERE e.id = $1
|
||||
LIMIT 1
|
||||
`
|
||||
|
|
@ -274,6 +287,7 @@ type GetEventWithSettingByIDRow struct {
|
|||
IsLive bool `json:"is_live"`
|
||||
Status string `json:"status"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
Source string `json:"source"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
|
|
@ -282,9 +296,10 @@ type GetEventWithSettingByIDRow struct {
|
|||
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"`
|
||||
WinningUpperLimit int64 `json:"winning_upper_limit"`
|
||||
UpdatedAt_2 pgtype.Timestamp `json:"updated_at_2"`
|
||||
LeagueCc pgtype.Text `json:"league_cc"`
|
||||
TotalOutcomes int64 `json:"total_outcomes"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithSettingByIDParams) (GetEventWithSettingByIDRow, error) {
|
||||
|
|
@ -312,6 +327,7 @@ func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithS
|
|||
&i.IsLive,
|
||||
&i.Status,
|
||||
&i.FetchedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Source,
|
||||
&i.DefaultIsActive,
|
||||
&i.DefaultIsFeatured,
|
||||
|
|
@ -321,14 +337,15 @@ func (q *Queries) GetEventWithSettingByID(ctx context.Context, arg GetEventWithS
|
|||
&i.IsActive,
|
||||
&i.IsFeatured,
|
||||
&i.WinningUpperLimit,
|
||||
&i.UpdatedAt,
|
||||
&i.UpdatedAt_2,
|
||||
&i.LeagueCc,
|
||||
&i.TotalOutcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetEventsWithSettings = `-- name: GetEventsWithSettings :many
|
||||
SELECT e.id, e.source_event_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,
|
||||
SELECT e.id, e.source_event_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.updated_at, e.source, e.default_is_active, e.default_is_featured, e.default_winning_upper_limit, e.is_monitored,
|
||||
ces.company_id,
|
||||
COALESCE(ces.is_active, e.default_is_active) AS is_active,
|
||||
COALESCE(ces.is_featured, e.default_is_featured) AS is_featured,
|
||||
|
|
@ -337,11 +354,18 @@ SELECT e.id, e.source_event_id, e.sport_id, e.match_name, e.home_team, e.away_te
|
|||
e.default_winning_upper_limit
|
||||
) AS winning_upper_limit,
|
||||
ces.updated_at,
|
||||
l.country_code as league_cc
|
||||
l.country_code as league_cc,
|
||||
COALESCE(om.total_outcomes, 0) AS total_outcomes
|
||||
FROM events e
|
||||
LEFT JOIN company_event_settings ces ON e.id = ces.event_id
|
||||
AND ces.company_id = $1
|
||||
JOIN leagues l ON l.id = e.league_id
|
||||
LEFT JOIN (
|
||||
SELECT event_id,
|
||||
SUM(number_of_outcomes) AS total_outcomes
|
||||
FROM odds_market
|
||||
GROUP BY event_id
|
||||
) om ON om.event_id = e.id
|
||||
WHERE (
|
||||
is_live = $2
|
||||
OR $2 IS NULL
|
||||
|
|
@ -432,6 +456,7 @@ type GetEventsWithSettingsRow struct {
|
|||
IsLive bool `json:"is_live"`
|
||||
Status string `json:"status"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
Source string `json:"source"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
|
|
@ -440,9 +465,10 @@ type GetEventsWithSettingsRow struct {
|
|||
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"`
|
||||
WinningUpperLimit int64 `json:"winning_upper_limit"`
|
||||
UpdatedAt_2 pgtype.Timestamp `json:"updated_at_2"`
|
||||
LeagueCc pgtype.Text `json:"league_cc"`
|
||||
TotalOutcomes int64 `json:"total_outcomes"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSettingsParams) ([]GetEventsWithSettingsRow, error) {
|
||||
|
|
@ -491,6 +517,7 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe
|
|||
&i.IsLive,
|
||||
&i.Status,
|
||||
&i.FetchedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Source,
|
||||
&i.DefaultIsActive,
|
||||
&i.DefaultIsFeatured,
|
||||
|
|
@ -500,8 +527,9 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe
|
|||
&i.IsActive,
|
||||
&i.IsFeatured,
|
||||
&i.WinningUpperLimit,
|
||||
&i.UpdatedAt,
|
||||
&i.UpdatedAt_2,
|
||||
&i.LeagueCc,
|
||||
&i.TotalOutcomes,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -514,7 +542,9 @@ func (q *Queries) GetEventsWithSettings(ctx context.Context, arg GetEventsWithSe
|
|||
}
|
||||
|
||||
const GetSportAndLeagueIDs = `-- name: GetSportAndLeagueIDs :one
|
||||
SELECT sport_id, league_id FROM events
|
||||
SELECT sport_id,
|
||||
league_id
|
||||
FROM events
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
|
|
@ -831,7 +861,7 @@ func (q *Queries) ListLiveEvents(ctx context.Context) ([]int64, error) {
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const SaveEventSettings = `-- name: SaveEventSettings :exec
|
||||
const SaveTenantEventSettings = `-- name: SaveTenantEventSettings :exec
|
||||
INSERT INTO company_event_settings (
|
||||
company_id,
|
||||
event_id,
|
||||
|
|
@ -846,16 +876,16 @@ SET is_active = EXCLUDED.is_active,
|
|||
winning_upper_limit = EXCLUDED.winning_upper_limit
|
||||
`
|
||||
|
||||
type SaveEventSettingsParams struct {
|
||||
type SaveTenantEventSettingsParams struct {
|
||||
CompanyID int64 `json:"company_id"`
|
||||
EventID int64 `json:"event_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
WinningUpperLimit pgtype.Int4 `json:"winning_upper_limit"`
|
||||
WinningUpperLimit pgtype.Int8 `json:"winning_upper_limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) SaveEventSettings(ctx context.Context, arg SaveEventSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, SaveEventSettings,
|
||||
func (q *Queries) SaveTenantEventSettings(ctx context.Context, arg SaveTenantEventSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, SaveTenantEventSettings,
|
||||
arg.CompanyID,
|
||||
arg.EventID,
|
||||
arg.IsActive,
|
||||
|
|
@ -867,7 +897,8 @@ func (q *Queries) SaveEventSettings(ctx context.Context, arg SaveEventSettingsPa
|
|||
|
||||
const UpdateEventMonitored = `-- name: UpdateEventMonitored :exec
|
||||
UPDATE events
|
||||
SET is_monitored = $1
|
||||
SET is_monitored = $1,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $2
|
||||
`
|
||||
|
||||
|
|
@ -881,6 +912,38 @@ func (q *Queries) UpdateEventMonitored(ctx context.Context, arg UpdateEventMonit
|
|||
return err
|
||||
}
|
||||
|
||||
const UpdateGlobalEventSettings = `-- name: UpdateGlobalEventSettings :exec
|
||||
UPDATE events
|
||||
SET default_is_active = COALESCE($2, default_is_active),
|
||||
default_is_featured = COALESCE(
|
||||
$3,
|
||||
default_is_featured
|
||||
),
|
||||
default_winning_upper_limit = COALESCE(
|
||||
$4,
|
||||
default_winning_upper_limit
|
||||
),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateGlobalEventSettingsParams struct {
|
||||
ID int64 `json:"id"`
|
||||
DefaultIsActive pgtype.Bool `json:"default_is_active"`
|
||||
DefaultIsFeatured pgtype.Bool `json:"default_is_featured"`
|
||||
DefaultWinningUpperLimit pgtype.Int8 `json:"default_winning_upper_limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateGlobalEventSettings(ctx context.Context, arg UpdateGlobalEventSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateGlobalEventSettings,
|
||||
arg.ID,
|
||||
arg.DefaultIsActive,
|
||||
arg.DefaultIsFeatured,
|
||||
arg.DefaultWinningUpperLimit,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateMatchResult = `-- name: UpdateMatchResult :exec
|
||||
UPDATE events
|
||||
SET score = $1,
|
||||
|
|
|
|||
|
|
@ -48,14 +48,19 @@ WHERE (
|
|||
name ILIKE '%' || $3 || '%'
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
default_is_active = $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
ORDER BY name ASC
|
||||
LIMIT $5 OFFSET $4
|
||||
LIMIT $6 OFFSET $5
|
||||
`
|
||||
|
||||
type GetAllLeaguesParams struct {
|
||||
CountryCode pgtype.Text `json:"country_code"`
|
||||
SportID pgtype.Int4 `json:"sport_id"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
Offset pgtype.Int4 `json:"offset"`
|
||||
Limit pgtype.Int4 `json:"limit"`
|
||||
}
|
||||
|
|
@ -65,6 +70,7 @@ func (q *Queries) GetAllLeagues(ctx context.Context, arg GetAllLeaguesParams) ([
|
|||
arg.CountryCode,
|
||||
arg.SportID,
|
||||
arg.Query,
|
||||
arg.IsActive,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
|
|
@ -199,6 +205,46 @@ func (q *Queries) GetAllLeaguesWithSettings(ctx context.Context, arg GetAllLeagu
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetTotalLeagues = `-- name: GetTotalLeagues :one
|
||||
SELECT COUNT(*)
|
||||
FROM leagues
|
||||
WHERE (
|
||||
country_code = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
sport_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
name ILIKE '%' || $3 || '%'
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
default_is_active = $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetTotalLeaguesParams struct {
|
||||
CountryCode pgtype.Text `json:"country_code"`
|
||||
SportID pgtype.Int4 `json:"sport_id"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalLeagues(ctx context.Context, arg GetTotalLeaguesParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalLeagues,
|
||||
arg.CountryCode,
|
||||
arg.SportID,
|
||||
arg.Query,
|
||||
arg.IsActive,
|
||||
)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const GetTotalLeaguesWithSettings = `-- name: GetTotalLeaguesWithSettings :one
|
||||
SELECT COUNT(*)
|
||||
FROM leagues l
|
||||
|
|
@ -292,7 +338,7 @@ func (q *Queries) InsertLeague(ctx context.Context, arg InsertLeagueParams) erro
|
|||
return err
|
||||
}
|
||||
|
||||
const InsertLeagueSettings = `-- name: InsertLeagueSettings :exec
|
||||
const SaveLeagueSettings = `-- name: SaveLeagueSettings :exec
|
||||
INSERT INTO company_league_settings (
|
||||
company_id,
|
||||
league_id,
|
||||
|
|
@ -305,15 +351,15 @@ SET is_active = EXCLUDED.is_active,
|
|||
is_featured = EXCLUDED.is_featured
|
||||
`
|
||||
|
||||
type InsertLeagueSettingsParams struct {
|
||||
type SaveLeagueSettingsParams struct {
|
||||
CompanyID int64 `json:"company_id"`
|
||||
LeagueID int64 `json:"league_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertLeagueSettings(ctx context.Context, arg InsertLeagueSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, InsertLeagueSettings,
|
||||
func (q *Queries) SaveLeagueSettings(ctx context.Context, arg SaveLeagueSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, SaveLeagueSettings,
|
||||
arg.CompanyID,
|
||||
arg.LeagueID,
|
||||
arg.IsActive,
|
||||
|
|
@ -322,6 +368,52 @@ func (q *Queries) InsertLeagueSettings(ctx context.Context, arg InsertLeagueSett
|
|||
return err
|
||||
}
|
||||
|
||||
const UpdateCompanyLeagueSettings = `-- name: UpdateCompanyLeagueSettings :exec
|
||||
UPDATE company_league_settings
|
||||
SET is_active = COALESCE($3, is_active),
|
||||
is_featured = COALESCE(
|
||||
$4,
|
||||
is_featured
|
||||
)
|
||||
WHERE league_id = $1
|
||||
AND company_id = $2
|
||||
`
|
||||
|
||||
type UpdateCompanyLeagueSettingsParams struct {
|
||||
LeagueID int64 `json:"league_id"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCompanyLeagueSettings(ctx context.Context, arg UpdateCompanyLeagueSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateCompanyLeagueSettings,
|
||||
arg.LeagueID,
|
||||
arg.CompanyID,
|
||||
arg.IsActive,
|
||||
arg.IsFeatured,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateGlobalLeagueSettings = `-- name: UpdateGlobalLeagueSettings :exec
|
||||
UPDATE leagues
|
||||
SET default_is_active = COALESCE($2, default_is_active),
|
||||
default_is_featured = COALESCE($3, default_is_featured)
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateGlobalLeagueSettingsParams struct {
|
||||
ID int64 `json:"id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateGlobalLeagueSettings(ctx context.Context, arg UpdateGlobalLeagueSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateGlobalLeagueSettings, arg.ID, arg.IsActive, arg.IsFeatured)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateLeague = `-- name: UpdateLeague :exec
|
||||
UPDATE leagues
|
||||
SET name = COALESCE($2, name),
|
||||
|
|
@ -349,31 +441,3 @@ func (q *Queries) UpdateLeague(ctx context.Context, arg UpdateLeagueParams) erro
|
|||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateLeagueSettings = `-- name: UpdateLeagueSettings :exec
|
||||
UPDATE company_league_settings
|
||||
SET is_active = COALESCE($3, is_active),
|
||||
is_featured = COALESCE(
|
||||
$4,
|
||||
is_featured
|
||||
)
|
||||
WHERE league_id = $1
|
||||
AND company_id = $2
|
||||
`
|
||||
|
||||
type UpdateLeagueSettingsParams struct {
|
||||
LeagueID int64 `json:"league_id"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateLeagueSettings(ctx context.Context, arg UpdateLeagueSettingsParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateLeagueSettings,
|
||||
arg.LeagueID,
|
||||
arg.CompanyID,
|
||||
arg.IsActive,
|
||||
arg.IsFeatured,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ type BetWithOutcome struct {
|
|||
FullName interface{} `json:"full_name"`
|
||||
PhoneNumber pgtype.Text `json:"phone_number"`
|
||||
Outcomes []BetOutcome `json:"outcomes"`
|
||||
CompanySlug string `json:"company_slug"`
|
||||
}
|
||||
|
||||
type Branch struct {
|
||||
|
|
@ -177,7 +178,7 @@ type CompanyEventSetting struct {
|
|||
EventID int64 `json:"event_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
IsFeatured pgtype.Bool `json:"is_featured"`
|
||||
WinningUpperLimit pgtype.Int4 `json:"winning_upper_limit"`
|
||||
WinningUpperLimit pgtype.Int8 `json:"winning_upper_limit"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -468,6 +469,7 @@ type Event struct {
|
|||
IsLive bool `json:"is_live"`
|
||||
Status string `json:"status"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
Source string `json:"source"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
|
|
@ -504,12 +506,14 @@ type EventWithCountry struct {
|
|||
IsLive bool `json:"is_live"`
|
||||
Status string `json:"status"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_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"`
|
||||
LeagueCc pgtype.Text `json:"league_cc"`
|
||||
TotalOutcomes int64 `json:"total_outcomes"`
|
||||
}
|
||||
|
||||
type EventWithSetting struct {
|
||||
|
|
@ -534,6 +538,7 @@ type EventWithSetting struct {
|
|||
IsLive bool `json:"is_live"`
|
||||
Status string `json:"status"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
Source string `json:"source"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
|
|
@ -542,9 +547,10 @@ type EventWithSetting struct {
|
|||
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"`
|
||||
WinningUpperLimit int64 `json:"winning_upper_limit"`
|
||||
CompanyUpdatedAt pgtype.Timestamp `json:"company_updated_at"`
|
||||
LeagueCc pgtype.Text `json:"league_cc"`
|
||||
TotalOutcomes int64 `json:"total_outcomes"`
|
||||
}
|
||||
|
||||
type ExchangeRate struct {
|
||||
|
|
@ -619,6 +625,8 @@ type Notification struct {
|
|||
Priority pgtype.Int4 `json:"priority"`
|
||||
Version int32 `json:"version"`
|
||||
Timestamp pgtype.Timestamptz `json:"timestamp"`
|
||||
Img pgtype.Text `json:"img"`
|
||||
Expires pgtype.Timestamptz `json:"expires"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
}
|
||||
|
||||
|
|
@ -640,6 +648,7 @@ type OddsMarket struct {
|
|||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
RawOdds []byte `json:"raw_odds"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -653,6 +662,7 @@ type OddsMarketWithEvent struct {
|
|||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
RawOdds []byte `json:"raw_odds"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -669,6 +679,7 @@ type OddsMarketWithSetting struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -696,6 +707,7 @@ type Raffle struct {
|
|||
Name string `json:"name"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
TicketLimit int32 `json:"ticket_limit"`
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
|
@ -824,6 +836,7 @@ type ShopBetDetail struct {
|
|||
TransactionVerified bool `json:"transaction_verified"`
|
||||
Status int32 `json:"status"`
|
||||
TotalOdds float32 `json:"total_odds"`
|
||||
FastCode string `json:"fast_code"`
|
||||
Outcomes []BetOutcome `json:"outcomes"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ INSERT INTO notifications (
|
|||
payload,
|
||||
priority,
|
||||
timestamp,
|
||||
expires,
|
||||
img,
|
||||
metadata
|
||||
)
|
||||
VALUES (
|
||||
|
|
@ -54,9 +56,11 @@ VALUES (
|
|||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
)
|
||||
RETURNING id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
RETURNING id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
`
|
||||
|
||||
type CreateNotificationParams struct {
|
||||
|
|
@ -72,6 +76,8 @@ type CreateNotificationParams struct {
|
|||
Payload []byte `json:"payload"`
|
||||
Priority pgtype.Int4 `json:"priority"`
|
||||
Timestamp pgtype.Timestamptz `json:"timestamp"`
|
||||
Expires pgtype.Timestamptz `json:"expires"`
|
||||
Img pgtype.Text `json:"img"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +95,8 @@ func (q *Queries) CreateNotification(ctx context.Context, arg CreateNotification
|
|||
arg.Payload,
|
||||
arg.Priority,
|
||||
arg.Timestamp,
|
||||
arg.Expires,
|
||||
arg.Img,
|
||||
arg.Metadata,
|
||||
)
|
||||
var i Notification
|
||||
|
|
@ -106,13 +114,25 @@ func (q *Queries) CreateNotification(ctx context.Context, arg CreateNotification
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const DeleteOldNotifications = `-- name: DeleteOldNotifications :exec
|
||||
DELETE FROM notifications
|
||||
WHERE expires < now()
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteOldNotifications(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, DeleteOldNotifications)
|
||||
return err
|
||||
}
|
||||
|
||||
const GetAllNotifications = `-- name: GetAllNotifications :many
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
FROM notifications
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT $1 OFFSET $2
|
||||
|
|
@ -146,6 +166,8 @@ func (q *Queries) GetAllNotifications(ctx context.Context, arg GetAllNotificatio
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -159,7 +181,7 @@ func (q *Queries) GetAllNotifications(ctx context.Context, arg GetAllNotificatio
|
|||
}
|
||||
|
||||
const GetNotification = `-- name: GetNotification :one
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
FROM notifications
|
||||
WHERE id = $1
|
||||
LIMIT 1
|
||||
|
|
@ -182,6 +204,8 @@ func (q *Queries) GetNotification(ctx context.Context, id string) (Notification,
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
)
|
||||
return i, err
|
||||
|
|
@ -254,7 +278,7 @@ func (q *Queries) GetUserNotificationCount(ctx context.Context, recipientID int6
|
|||
}
|
||||
|
||||
const GetUserNotifications = `-- name: GetUserNotifications :many
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
FROM notifications
|
||||
WHERE recipient_id = $1
|
||||
ORDER BY timestamp DESC
|
||||
|
|
@ -290,6 +314,8 @@ func (q *Queries) GetUserNotifications(ctx context.Context, arg GetUserNotificat
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -303,7 +329,7 @@ func (q *Queries) GetUserNotifications(ctx context.Context, arg GetUserNotificat
|
|||
}
|
||||
|
||||
const ListFailedNotifications = `-- name: ListFailedNotifications :many
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
SELECT id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
FROM notifications
|
||||
WHERE delivery_status = 'failed'
|
||||
AND timestamp < NOW() - INTERVAL '1 hour'
|
||||
|
|
@ -334,6 +360,8 @@ func (q *Queries) ListFailedNotifications(ctx context.Context, limit int32) ([]N
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -378,7 +406,7 @@ SET delivery_status = $2,
|
|||
is_read = $3,
|
||||
metadata = $4
|
||||
WHERE id = $1
|
||||
RETURNING id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, metadata
|
||||
RETURNING id, recipient_id, type, level, error_severity, reciever, is_read, delivery_status, delivery_channel, payload, priority, version, timestamp, img, expires, metadata
|
||||
`
|
||||
|
||||
type UpdateNotificationStatusParams struct {
|
||||
|
|
@ -410,6 +438,8 @@ func (q *Queries) UpdateNotificationStatus(ctx context.Context, arg UpdateNotifi
|
|||
&i.Priority,
|
||||
&i.Version,
|
||||
&i.Timestamp,
|
||||
&i.Img,
|
||||
&i.Expires,
|
||||
&i.Metadata,
|
||||
)
|
||||
return i, err
|
||||
|
|
|
|||
|
|
@ -11,6 +11,32 @@ import (
|
|||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const DeleteAllCompanyOddsSetting = `-- name: DeleteAllCompanyOddsSetting :exec
|
||||
DELETE FROM company_odd_settings
|
||||
WHERE company_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteAllCompanyOddsSetting(ctx context.Context, companyID int64) error {
|
||||
_, err := q.db.Exec(ctx, DeleteAllCompanyOddsSetting, companyID)
|
||||
return err
|
||||
}
|
||||
|
||||
const DeleteCompanyOddsSettingByOddMarketID = `-- name: DeleteCompanyOddsSettingByOddMarketID :exec
|
||||
DELETE FROM company_odd_settings
|
||||
WHERE company_id = $1
|
||||
AND odds_market_id = $2
|
||||
`
|
||||
|
||||
type DeleteCompanyOddsSettingByOddMarketIDParams struct {
|
||||
CompanyID int64 `json:"company_id"`
|
||||
OddsMarketID int64 `json:"odds_market_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, arg DeleteCompanyOddsSettingByOddMarketIDParams) error {
|
||||
_, err := q.db.Exec(ctx, DeleteCompanyOddsSettingByOddMarketID, arg.CompanyID, arg.OddsMarketID)
|
||||
return err
|
||||
}
|
||||
|
||||
const DeleteOddsForEvent = `-- name: DeleteOddsForEvent :exec
|
||||
DELETE FROM odds_market
|
||||
Where event_id = $1
|
||||
|
|
@ -22,7 +48,7 @@ func (q *Queries) DeleteOddsForEvent(ctx context.Context, eventID int64) error {
|
|||
}
|
||||
|
||||
const GetAllOdds = `-- name: GetAllOdds :many
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
FROM odds_market_with_event
|
||||
LIMIT $2 OFFSET $1
|
||||
`
|
||||
|
|
@ -49,6 +75,7 @@ func (q *Queries) GetAllOdds(ctx context.Context, arg GetAllOddsParams) ([]OddsM
|
|||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.RawOdds,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -74,6 +101,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -100,6 +128,7 @@ type GetAllOddsWithSettingsRow struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -125,6 +154,7 @@ func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWith
|
|||
&i.MarketName,
|
||||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -144,7 +174,7 @@ func (q *Queries) GetAllOddsWithSettings(ctx context.Context, arg GetAllOddsWith
|
|||
}
|
||||
|
||||
const GetOddByID = `-- name: GetOddByID :one
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
FROM odds_market_with_event
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -160,6 +190,7 @@ func (q *Queries) GetOddByID(ctx context.Context, id int64) (OddsMarketWithEvent
|
|||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.RawOdds,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -172,7 +203,7 @@ func (q *Queries) GetOddByID(ctx context.Context, id int64) (OddsMarketWithEvent
|
|||
}
|
||||
|
||||
const GetOddsByEventID = `-- name: GetOddsByEventID :many
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
FROM odds_market_with_event
|
||||
WHERE event_id = $1
|
||||
AND (
|
||||
|
|
@ -223,6 +254,7 @@ func (q *Queries) GetOddsByEventID(ctx context.Context, arg GetOddsByEventIDPara
|
|||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.RawOdds,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -242,7 +274,7 @@ func (q *Queries) GetOddsByEventID(ctx context.Context, arg GetOddsByEventIDPara
|
|||
}
|
||||
|
||||
const GetOddsByMarketID = `-- name: GetOddsByMarketID :one
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
SELECT id, event_id, market_type, market_name, market_category, market_id, raw_odds, number_of_outcomes, default_is_active, fetched_at, expires_at, is_monitored, is_live, status, source
|
||||
FROM odds_market_with_event
|
||||
WHERE market_id = $1
|
||||
AND event_id = $2
|
||||
|
|
@ -264,6 +296,7 @@ func (q *Queries) GetOddsByMarketID(ctx context.Context, arg GetOddsByMarketIDPa
|
|||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.RawOdds,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -282,6 +315,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -310,6 +344,7 @@ type GetOddsWithSettingsByEventIDRow struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -340,6 +375,7 @@ func (q *Queries) GetOddsWithSettingsByEventID(ctx context.Context, arg GetOddsW
|
|||
&i.MarketName,
|
||||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -365,6 +401,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -390,6 +427,7 @@ type GetOddsWithSettingsByIDRow struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -409,6 +447,7 @@ func (q *Queries) GetOddsWithSettingsByID(ctx context.Context, arg GetOddsWithSe
|
|||
&i.MarketName,
|
||||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -427,6 +466,7 @@ SELECT o.id,
|
|||
o.market_name,
|
||||
o.market_category,
|
||||
o.market_id,
|
||||
o.number_of_outcomes,
|
||||
o.default_is_active,
|
||||
o.fetched_at,
|
||||
o.expires_at,
|
||||
|
|
@ -454,6 +494,7 @@ type GetOddsWithSettingsByMarketIDRow struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -473,6 +514,7 @@ func (q *Queries) GetOddsWithSettingsByMarketID(ctx context.Context, arg GetOdds
|
|||
&i.MarketName,
|
||||
&i.MarketCategory,
|
||||
&i.MarketID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.DefaultIsActive,
|
||||
&i.FetchedAt,
|
||||
&i.ExpiresAt,
|
||||
|
|
@ -491,6 +533,7 @@ INSERT INTO odds_market (
|
|||
market_name,
|
||||
market_category,
|
||||
market_id,
|
||||
number_of_outcomes,
|
||||
raw_odds,
|
||||
fetched_at,
|
||||
expires_at
|
||||
|
|
@ -503,13 +546,15 @@ VALUES (
|
|||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8
|
||||
$8,
|
||||
$9
|
||||
) ON CONFLICT (event_id, market_id) DO
|
||||
UPDATE
|
||||
SET market_type = EXCLUDED.market_type,
|
||||
market_name = EXCLUDED.market_name,
|
||||
market_category = EXCLUDED.market_category,
|
||||
raw_odds = EXCLUDED.raw_odds,
|
||||
number_of_outcomes = EXCLUDED.number_of_outcomes,
|
||||
fetched_at = EXCLUDED.fetched_at,
|
||||
expires_at = EXCLUDED.expires_at
|
||||
`
|
||||
|
|
@ -520,6 +565,7 @@ type InsertOddsMarketParams struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
RawOdds []byte `json:"raw_odds"`
|
||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
|
|
@ -532,6 +578,7 @@ func (q *Queries) InsertOddsMarket(ctx context.Context, arg InsertOddsMarketPara
|
|||
arg.MarketName,
|
||||
arg.MarketCategory,
|
||||
arg.MarketID,
|
||||
arg.NumberOfOutcomes,
|
||||
arg.RawOdds,
|
||||
arg.FetchedAt,
|
||||
arg.ExpiresAt,
|
||||
|
|
@ -568,3 +615,19 @@ func (q *Queries) SaveOddSettings(ctx context.Context, arg SaveOddSettingsParams
|
|||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateGlobalOddsSetting = `-- name: UpdateGlobalOddsSetting :exec
|
||||
UPDATE odds_market
|
||||
SET default_is_active = COALESCE($2, default_is_active)
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateGlobalOddsSettingParams struct {
|
||||
ID int64 `json:"id"`
|
||||
DefaultIsActive pgtype.Bool `json:"default_is_active"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateGlobalOddsSetting(ctx context.Context, arg UpdateGlobalOddsSettingParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateGlobalOddsSetting, arg.ID, arg.DefaultIsActive)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,19 @@ func (q *Queries) AddSportRaffleFilter(ctx context.Context, arg AddSportRaffleFi
|
|||
return i, err
|
||||
}
|
||||
|
||||
const CheckSportRaffleHasFilter = `-- name: CheckSportRaffleHasFilter :one
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM raffle_sport_filters WHERE raffle_id = $1
|
||||
) AS has_filter
|
||||
`
|
||||
|
||||
func (q *Queries) CheckSportRaffleHasFilter(ctx context.Context, raffleID int32) (bool, error) {
|
||||
row := q.db.QueryRow(ctx, CheckSportRaffleHasFilter, raffleID)
|
||||
var has_filter bool
|
||||
err := row.Scan(&has_filter)
|
||||
return has_filter, err
|
||||
}
|
||||
|
||||
const CheckValidSportRaffleFilter = `-- name: CheckValidSportRaffleFilter :one
|
||||
SELECT COUNT(*) > 0 AS exists
|
||||
FROM raffle_sport_filters
|
||||
|
|
@ -57,15 +70,16 @@ func (q *Queries) CheckValidSportRaffleFilter(ctx context.Context, arg CheckVali
|
|||
}
|
||||
|
||||
const CreateRaffle = `-- name: CreateRaffle :one
|
||||
INSERT INTO raffles (company_id, name, expires_at, type)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, company_id, name, created_at, expires_at, type, status
|
||||
INSERT INTO raffles (company_id, name, expires_at, ticket_limit, type)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, company_id, name, created_at, expires_at, ticket_limit, type, status
|
||||
`
|
||||
|
||||
type CreateRaffleParams struct {
|
||||
CompanyID int32 `json:"company_id"`
|
||||
Name string `json:"name"`
|
||||
ExpiresAt pgtype.Timestamp `json:"expires_at"`
|
||||
TicketLimit int32 `json:"ticket_limit"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
|
|
@ -74,6 +88,7 @@ func (q *Queries) CreateRaffle(ctx context.Context, arg CreateRaffleParams) (Raf
|
|||
arg.CompanyID,
|
||||
arg.Name,
|
||||
arg.ExpiresAt,
|
||||
arg.TicketLimit,
|
||||
arg.Type,
|
||||
)
|
||||
var i Raffle
|
||||
|
|
@ -83,6 +98,7 @@ func (q *Queries) CreateRaffle(ctx context.Context, arg CreateRaffleParams) (Raf
|
|||
&i.Name,
|
||||
&i.CreatedAt,
|
||||
&i.ExpiresAt,
|
||||
&i.TicketLimit,
|
||||
&i.Type,
|
||||
&i.Status,
|
||||
)
|
||||
|
|
@ -140,7 +156,7 @@ func (q *Queries) CreateRaffleWinner(ctx context.Context, arg CreateRaffleWinner
|
|||
const DeleteRaffle = `-- name: DeleteRaffle :one
|
||||
DELETE FROM raffles
|
||||
WHERE id = $1
|
||||
RETURNING id, company_id, name, created_at, expires_at, type, status
|
||||
RETURNING id, company_id, name, created_at, expires_at, ticket_limit, type, status
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteRaffle(ctx context.Context, id int32) (Raffle, error) {
|
||||
|
|
@ -152,6 +168,7 @@ func (q *Queries) DeleteRaffle(ctx context.Context, id int32) (Raffle, error) {
|
|||
&i.Name,
|
||||
&i.CreatedAt,
|
||||
&i.ExpiresAt,
|
||||
&i.TicketLimit,
|
||||
&i.Type,
|
||||
&i.Status,
|
||||
)
|
||||
|
|
@ -219,8 +236,40 @@ func (q *Queries) GetRaffleStanding(ctx context.Context, arg GetRaffleStandingPa
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetRaffleTicketCount = `-- name: GetRaffleTicketCount :one
|
||||
SELECT COUNT(*)
|
||||
FROM raffle_tickets
|
||||
WHERE raffle_id = $1
|
||||
AND user_id = $2
|
||||
`
|
||||
|
||||
type GetRaffleTicketCountParams struct {
|
||||
RaffleID int32 `json:"raffle_id"`
|
||||
UserID int32 `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRaffleTicketCount(ctx context.Context, arg GetRaffleTicketCountParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetRaffleTicketCount, arg.RaffleID, arg.UserID)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const GetRaffleTicketLimit = `-- name: GetRaffleTicketLimit :one
|
||||
SELECT ticket_limit
|
||||
FROM raffles
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRaffleTicketLimit(ctx context.Context, id int32) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, GetRaffleTicketLimit, id)
|
||||
var ticket_limit int32
|
||||
err := row.Scan(&ticket_limit)
|
||||
return ticket_limit, err
|
||||
}
|
||||
|
||||
const GetRafflesOfCompany = `-- name: GetRafflesOfCompany :many
|
||||
SELECT id, company_id, name, created_at, expires_at, type, status FROM raffles WHERE company_id = $1
|
||||
SELECT id, company_id, name, created_at, expires_at, ticket_limit, type, status FROM raffles WHERE company_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]Raffle, error) {
|
||||
|
|
@ -238,6 +287,7 @@ func (q *Queries) GetRafflesOfCompany(ctx context.Context, companyID int32) ([]R
|
|||
&i.Name,
|
||||
&i.CreatedAt,
|
||||
&i.ExpiresAt,
|
||||
&i.TicketLimit,
|
||||
&i.Type,
|
||||
&i.Status,
|
||||
); err != nil {
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ func (q *Queries) CreateShopTransaction(ctx context.Context, arg CreateShopTrans
|
|||
}
|
||||
|
||||
const GetAllShopBets = `-- name: GetAllShopBets :many
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, outcomes
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, fast_code, outcomes
|
||||
FROM shop_bet_detail
|
||||
WHERE (
|
||||
full_name ILIKE '%' || $1 || '%'
|
||||
|
|
@ -239,6 +239,7 @@ func (q *Queries) GetAllShopBets(ctx context.Context, arg GetAllShopBetsParams)
|
|||
&i.TransactionVerified,
|
||||
&i.Status,
|
||||
&i.TotalOdds,
|
||||
&i.FastCode,
|
||||
&i.Outcomes,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -419,7 +420,7 @@ func (q *Queries) GetAllShopTransactions(ctx context.Context, arg GetAllShopTran
|
|||
}
|
||||
|
||||
const GetShopBetByBetID = `-- name: GetShopBetByBetID :one
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, outcomes
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, fast_code, outcomes
|
||||
FROM shop_bet_detail
|
||||
WHERE bet_id = $1
|
||||
`
|
||||
|
|
@ -445,13 +446,14 @@ func (q *Queries) GetShopBetByBetID(ctx context.Context, betID int64) (ShopBetDe
|
|||
&i.TransactionVerified,
|
||||
&i.Status,
|
||||
&i.TotalOdds,
|
||||
&i.FastCode,
|
||||
&i.Outcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetShopBetByCashoutID = `-- name: GetShopBetByCashoutID :one
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, outcomes
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, fast_code, outcomes
|
||||
FROM shop_bet_detail
|
||||
WHERE cashout_id = $1
|
||||
`
|
||||
|
|
@ -477,13 +479,14 @@ func (q *Queries) GetShopBetByCashoutID(ctx context.Context, cashoutID string) (
|
|||
&i.TransactionVerified,
|
||||
&i.Status,
|
||||
&i.TotalOdds,
|
||||
&i.FastCode,
|
||||
&i.Outcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetShopBetByID = `-- name: GetShopBetByID :one
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, outcomes
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, fast_code, outcomes
|
||||
FROM shop_bet_detail
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -509,13 +512,14 @@ func (q *Queries) GetShopBetByID(ctx context.Context, id int64) (ShopBetDetail,
|
|||
&i.TransactionVerified,
|
||||
&i.Status,
|
||||
&i.TotalOdds,
|
||||
&i.FastCode,
|
||||
&i.Outcomes,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetShopBetByShopTransactionID = `-- name: GetShopBetByShopTransactionID :one
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, outcomes
|
||||
SELECT id, shop_transaction_id, cashout_id, cashed_out_by, bet_id, number_of_outcomes, cashed_out, created_at, updated_at, customer_full_name, customer_phone_number, branch_id, company_id, amount, transaction_verified, status, total_odds, fast_code, outcomes
|
||||
FROM shop_bet_detail
|
||||
WHERE shop_transaction_id = $1
|
||||
`
|
||||
|
|
@ -541,6 +545,7 @@ func (q *Queries) GetShopBetByShopTransactionID(ctx context.Context, shopTransac
|
|||
&i.TransactionVerified,
|
||||
&i.Status,
|
||||
&i.TotalOdds,
|
||||
&i.FastCode,
|
||||
&i.Outcomes,
|
||||
)
|
||||
return i, err
|
||||
|
|
|
|||
8
go.mod
8
go.mod
|
|
@ -81,19 +81,11 @@ require (
|
|||
require github.com/twilio/twilio-go v1.26.3
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.10.0 // direct
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/segmentio/kafka-go v0.4.48 // direct
|
||||
)
|
||||
|
||||
// require github.com/AnaniyaBelew/ArifpayGoPlugin v0.0.0-20231127130208-54b9bc51118f
|
||||
|
||||
// require github.com/AnaniyaBelew/ArifpayGoPlugin v0.0.0-20231127130208-54b9bc51118f // direct
|
||||
|
|
|
|||
33
go.sum
33
go.sum
|
|
@ -1,5 +1,3 @@
|
|||
github.com/AnaniyaBelew/ArifpayGoPlugin v0.0.0-20231127130208-54b9bc51118f h1:UOp9At84RG8OT2Nw2TQidYWaoW1rAfTqChOJLdhYcm8=
|
||||
github.com/AnaniyaBelew/ArifpayGoPlugin v0.0.0-20231127130208-54b9bc51118f/go.mod h1:N2NQ6ad3i+oLQU+MlPci2f7mx6Mtg+wUcvzCv77KCl8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
|
|
@ -12,17 +10,11 @@ github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
|
|||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
|
|
@ -31,8 +23,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
|
@ -91,7 +81,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
|
|||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
|
|
@ -129,15 +118,11 @@ github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJ
|
|||
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=
|
||||
github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/resend/resend-go/v2 v2.20.0 h1:MrIrgV0aHhwRgmcRPw33Nexn6aGJvCvG2XwfFpAMBGM=
|
||||
github.com/resend/resend-go/v2 v2.20.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
|
|
@ -150,8 +135,6 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4
|
|||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/segmentio/kafka-go v0.4.48 h1:9jyu9CWK4W5W+SroCe8EffbrRZVqAOkuaLd/ApID4Vs=
|
||||
github.com/segmentio/kafka-go v0.4.48/go.mod h1:HjF6XbOKh0Pjlkr5GVZxt6CsjjwnmhVOfURM5KMd8qg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
|
|
@ -215,12 +198,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
|
@ -233,15 +214,11 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -257,25 +234,16 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -284,7 +252,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ type GetBet struct {
|
|||
PhoneNumber string
|
||||
UserID int64
|
||||
CompanyID int64
|
||||
CompanySlug string
|
||||
IsShopBet bool
|
||||
CashedOut bool
|
||||
Outcomes []BetOutcome
|
||||
|
|
@ -157,12 +158,43 @@ type BetRes struct {
|
|||
Fullname string `json:"full_name" example:"John Smith"`
|
||||
UserID int64 `json:"user_id" example:"2"`
|
||||
CompanyID int64 `json:"company_id" example:"1"`
|
||||
CompanySlug string `json:"company_slug" example:"fortune"`
|
||||
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
||||
CashedOut bool `json:"cashed_out" example:"false"`
|
||||
CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"`
|
||||
FastCode string `json:"fast_code"`
|
||||
}
|
||||
|
||||
type BetOutcomeViewRes struct {
|
||||
ID int64 `json:"id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
CompanyName string `json:"company_name"`
|
||||
SportID int64 `json:"sport_id"`
|
||||
EventID int64 `json:"event_id"`
|
||||
OddID int64 `json:"odd_id"`
|
||||
HomeTeamName string `json:"home_team_name"`
|
||||
AwayTeamName string `json:"away_team_name"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
MarketName string `json:"market_name"`
|
||||
Odd float32 `json:"odd"`
|
||||
OddName string `json:"odd_name"`
|
||||
OddHeader string `json:"odd_header"`
|
||||
OddHandicap string `json:"odd_handicap"`
|
||||
Status OutcomeStatus `json:"status"`
|
||||
Expires time.Time `json:"expires"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Amount int64 `json:"amount"`
|
||||
TotalOdds float32 `json:"total_odds"`
|
||||
}
|
||||
|
||||
type BetOutcomeViewFilter struct {
|
||||
OutcomeStatus ValidOutcomeStatus
|
||||
CompanyID ValidInt64
|
||||
Limit ValidInt32
|
||||
Offset ValidInt32
|
||||
}
|
||||
|
||||
func ConvertCreateBetRes(bet Bet, createdNumber int64) CreateBetRes {
|
||||
return CreateBetRes{
|
||||
ID: bet.ID,
|
||||
|
|
@ -186,6 +218,7 @@ func ConvertBet(bet GetBet) BetRes {
|
|||
Fullname: bet.FullName,
|
||||
UserID: bet.UserID,
|
||||
CompanyID: bet.CompanyID,
|
||||
CompanySlug: bet.CompanySlug,
|
||||
Outcomes: bet.Outcomes,
|
||||
IsShopBet: bet.IsShopBet,
|
||||
CashedOut: bet.CashedOut,
|
||||
|
|
@ -228,6 +261,30 @@ func ConvertDBBetOutcomes(outcome dbgen.BetOutcome) BetOutcome {
|
|||
Expires: outcome.Expires.Time,
|
||||
}
|
||||
}
|
||||
func ConvertDBBetOutcomesView(outcome dbgen.GetBetOutcomeViewByEventIDRow) BetOutcomeViewRes {
|
||||
return BetOutcomeViewRes{
|
||||
ID: outcome.ID,
|
||||
BetID: outcome.BetID,
|
||||
CompanyName: outcome.CompanyName,
|
||||
SportID: outcome.SportID,
|
||||
EventID: outcome.EventID,
|
||||
OddID: outcome.OddID,
|
||||
HomeTeamName: outcome.HomeTeamName,
|
||||
AwayTeamName: outcome.AwayTeamName,
|
||||
MarketID: outcome.MarketID,
|
||||
MarketName: outcome.MarketName,
|
||||
Odd: outcome.Odd,
|
||||
OddName: outcome.OddName,
|
||||
OddHeader: outcome.OddHeader,
|
||||
OddHandicap: outcome.OddHandicap,
|
||||
Status: OutcomeStatus(outcome.Status),
|
||||
Expires: outcome.Expires.Time,
|
||||
FirstName: outcome.FirstName,
|
||||
LastName: outcome.LastName,
|
||||
Amount: outcome.Amount,
|
||||
TotalOdds: outcome.TotalOdds,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertDBBetWithOutcomes(bet dbgen.BetWithOutcome) GetBet {
|
||||
var outcomes []BetOutcome = make([]BetOutcome, 0, len(bet.Outcomes))
|
||||
|
|
@ -239,6 +296,7 @@ func ConvertDBBetWithOutcomes(bet dbgen.BetWithOutcome) GetBet {
|
|||
return GetBet{
|
||||
ID: bet.ID,
|
||||
CompanyID: bet.CompanyID,
|
||||
CompanySlug: bet.CompanySlug,
|
||||
Amount: Currency(bet.Amount),
|
||||
TotalOdds: bet.TotalOdds,
|
||||
Status: OutcomeStatus(bet.Status),
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ type CreateCompany struct {
|
|||
AdminID int64
|
||||
WalletID int64
|
||||
DeductedPercentage float32
|
||||
Slug string
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
type UpdateCompany struct {
|
||||
|
|
@ -53,18 +55,22 @@ type UpdateCompany struct {
|
|||
AdminID ValidInt64
|
||||
IsActive ValidBool
|
||||
DeductedPercentage ValidFloat32
|
||||
Slug ValidString
|
||||
}
|
||||
|
||||
type CreateCompanyReq struct {
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage" example:"0.1" validate:"lt=1"`
|
||||
Slug string `json:"slug"`
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
type UpdateCompanyReq struct {
|
||||
Name *string `json:"name,omitempty" example:"CompanyName"`
|
||||
AdminID *int64 `json:"admin_id,omitempty" example:"1"`
|
||||
IsActive *bool `json:"is_active,omitempty" example:"true"`
|
||||
DeductedPercentage *float32 `json:"deducted_percentage,omitempty" example:"0.1" validate:"lt=1"`
|
||||
Slug *string `json:"slug"`
|
||||
}
|
||||
|
||||
type CompanyRes struct {
|
||||
|
|
@ -113,13 +119,14 @@ func ConvertGetCompany(company GetCompany) GetCompanyRes {
|
|||
}
|
||||
}
|
||||
|
||||
func ConvertCreateCompany(company CreateCompany, uniqueSlug string) dbgen.CreateCompanyParams {
|
||||
func ConvertCreateCompany(company CreateCompany) dbgen.CreateCompanyParams {
|
||||
return dbgen.CreateCompanyParams{
|
||||
Name: company.Name,
|
||||
Slug: uniqueSlug,
|
||||
Slug: company.Slug,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
DeductedPercentage: company.DeductedPercentage,
|
||||
IsActive: company.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,30 +162,21 @@ func ConvertDBCompanyDetails(dbCompany dbgen.CompaniesDetail) GetCompany {
|
|||
func ConvertUpdateCompany(updateCompany UpdateCompany) dbgen.UpdateCompanyParams {
|
||||
newUpdateCompany := dbgen.UpdateCompanyParams{
|
||||
ID: updateCompany.ID,
|
||||
Name: pgtype.Text{
|
||||
String: updateCompany.Name.Value,
|
||||
Valid: updateCompany.Name.Valid,
|
||||
},
|
||||
AdminID: pgtype.Int8{
|
||||
Int64: updateCompany.AdminID.Value,
|
||||
Valid: updateCompany.AdminID.Valid,
|
||||
},
|
||||
IsActive: pgtype.Bool{
|
||||
Bool: updateCompany.IsActive.Value,
|
||||
Valid: updateCompany.IsActive.Valid,
|
||||
},
|
||||
DeductedPercentage: pgtype.Float4{
|
||||
Float32: updateCompany.DeductedPercentage.Value,
|
||||
Valid: updateCompany.DeductedPercentage.Valid,
|
||||
},
|
||||
Name: updateCompany.Name.ToPG(),
|
||||
AdminID: updateCompany.AdminID.ToPG(),
|
||||
IsActive: updateCompany.IsActive.ToPG(),
|
||||
DeductedPercentage: updateCompany.DeductedPercentage.ToPG(),
|
||||
Slug: updateCompany.Slug.ToPG(),
|
||||
}
|
||||
|
||||
return newUpdateCompany
|
||||
}
|
||||
|
||||
func ConvertUpdateCompanyReq(req UpdateCompanyReq) UpdateCompany {
|
||||
func ConvertUpdateCompanyReq(req UpdateCompanyReq, companyID int64) UpdateCompany {
|
||||
var updateCompany UpdateCompany
|
||||
|
||||
updateCompany.ID = companyID
|
||||
|
||||
if req.Name != nil {
|
||||
updateCompany.Name = ValidString{
|
||||
Value: *req.Name,
|
||||
|
|
@ -206,6 +204,12 @@ func ConvertUpdateCompanyReq(req UpdateCompanyReq) UpdateCompany {
|
|||
Valid: true,
|
||||
}
|
||||
}
|
||||
if req.Slug != nil {
|
||||
updateCompany.Slug = ValidString{
|
||||
Value: *req.Slug,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
return updateCompany
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,43 @@ func (m Currency) String() string {
|
|||
return fmt.Sprintf("$%.2f", m.Float32())
|
||||
}
|
||||
|
||||
|
||||
// TODO: Change the currency to this format when implementing multi-currency
|
||||
// type Currency struct {
|
||||
// Value int64
|
||||
// Type IntCurrency
|
||||
// }
|
||||
|
||||
// // ToCurrency converts a float32 (like 12.34) into Currency (stored in cents).
|
||||
// func NewCurrency(f float32, currencyType IntCurrency) Currency {
|
||||
// cents := math.Round(float64(f) * 100) // avoid float32 precision issues
|
||||
// return Currency{
|
||||
// Value: int64(cents),
|
||||
// Type: currencyType,
|
||||
// }
|
||||
// }
|
||||
|
||||
// func NewBase(v int64) Currency {
|
||||
// return Currency{
|
||||
// Value: v,
|
||||
// Type: BASE,
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Float32 converts a Currency back into float32 (like 12.34).
|
||||
// func (m Currency) Float32() float32 {
|
||||
// return float32(m.Value) / 100
|
||||
// }
|
||||
|
||||
// // String returns a formatted Currency value for display.
|
||||
// func (m Currency) String() string {
|
||||
// return fmt.Sprintf("$%.2f", m.Float32())
|
||||
// }
|
||||
|
||||
type IntCurrency string
|
||||
|
||||
const (
|
||||
BASE IntCurrency = "BASE"
|
||||
ETB IntCurrency = "ETB" // Ethiopian Birr
|
||||
NGN IntCurrency = "NGN" // Nigerian Naira
|
||||
ZAR IntCurrency = "ZAR" // South African Rand
|
||||
|
|
|
|||
|
|
@ -486,25 +486,23 @@ type CreateEnetpulseFixture struct {
|
|||
|
||||
// Full domain model
|
||||
type EnetpulseFixture struct {
|
||||
FixtureID string
|
||||
Name string
|
||||
SportFK string
|
||||
TournamentFK string
|
||||
TournamentTemplateFK string
|
||||
TournamentStageFK string
|
||||
TournamentStageName string
|
||||
TournamentName string
|
||||
TournamentTemplateName string
|
||||
SportName string
|
||||
Gender string
|
||||
StartDate time.Time
|
||||
StatusType string
|
||||
StatusDescFK string
|
||||
RoundTypeFK string
|
||||
UpdatesCount int
|
||||
LastUpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
FixtureID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SportFK string `json:"sportFK"`
|
||||
TournamentFK string `json:"tournamentFK"`
|
||||
TournamentTemplateFK string `json:"tournament_templateFK"`
|
||||
TournamentStageFK string `json:"tournament_stageFK"`
|
||||
TournamentStageName string `json:"tournament_stage_name"`
|
||||
TournamentName string `json:"tournament_name"`
|
||||
TournamentTemplateName string `json:"tournament_template_name"`
|
||||
SportName string `json:"sport_name"`
|
||||
Gender string `json:"gender"`
|
||||
StartDate string `json:"startdate"` // ISO 8601
|
||||
StatusType string `json:"status_type"`
|
||||
StatusDescFK string `json:"status_descFK"`
|
||||
RoundTypeFK string `json:"round_typeFK"`
|
||||
UpdatesCount string `json:"n"` // convert to int
|
||||
LastUpdatedAt string `json:"ut"` // parse to time.Time
|
||||
}
|
||||
|
||||
type CreateEnetpulseResult struct {
|
||||
|
|
@ -604,7 +602,7 @@ type CreateEnetpulseOutcomeType struct {
|
|||
LastUpdatedAt time.Time `json:"last_updated_at"`
|
||||
}
|
||||
|
||||
type EnetpulsePreodds struct {
|
||||
type EnetpulsePreoddsTemp struct {
|
||||
PreoddsID string `json:"preodds_id"`
|
||||
EventFK string `json:"event_fk"`
|
||||
OutcomeTypeFK string `json:"outcome_type_fk"`
|
||||
|
|
@ -668,3 +666,41 @@ type EnetpulsePreoddsBettingOffer struct {
|
|||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type EnetpulseFixtureWithPreodds struct {
|
||||
FixtureID string
|
||||
FixtureApiID string
|
||||
FixtureName string
|
||||
SportFk string
|
||||
TournamentFk string
|
||||
TournamentTemplateFk string
|
||||
TournamentStageFk string
|
||||
StartDate time.Time
|
||||
StatusType string
|
||||
StatusDescFk string
|
||||
RoundTypeFk string
|
||||
UpdatesCount int32
|
||||
LastUpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Preodds []EnetpulsePreodds
|
||||
}
|
||||
|
||||
type EnetpulsePreodds struct {
|
||||
ID int64
|
||||
PreoddsID string
|
||||
EventFK int64
|
||||
OutcomeTypeFK int32
|
||||
OutcomeScopeFK int32
|
||||
OutcomeSubtypeFK int32
|
||||
EventParticipantNumber int32
|
||||
IParam string
|
||||
IParam2 string
|
||||
DParam string
|
||||
DParam2 string
|
||||
SParam string
|
||||
UpdatesCount int32
|
||||
LastUpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
|
|
@ -50,6 +51,58 @@ const (
|
|||
EVENT_SOURCE_ENET EventSource = "enetpulse"
|
||||
)
|
||||
|
||||
// --- EventStatus Validation ---
|
||||
func (s EventStatus) IsValid() bool {
|
||||
switch s {
|
||||
case STATUS_PENDING,
|
||||
STATUS_IN_PLAY,
|
||||
STATUS_TO_BE_FIXED,
|
||||
STATUS_ENDED,
|
||||
STATUS_POSTPONED,
|
||||
STATUS_CANCELLED,
|
||||
STATUS_WALKOVER,
|
||||
STATUS_INTERRUPTED,
|
||||
STATUS_ABANDONED,
|
||||
STATUS_RETIRED,
|
||||
STATUS_SUSPENDED,
|
||||
STATUS_DECIDED_BY_FA,
|
||||
STATUS_REMOVED:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func ParseEventStatus(val string) (EventStatus, error) {
|
||||
s := EventStatus(val)
|
||||
if !s.IsValid() {
|
||||
return "", fmt.Errorf("invalid EventStatus: %q", val)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// --- EventSource Validation ---
|
||||
func (s EventSource) IsValid() bool {
|
||||
switch s {
|
||||
case EVENT_SOURCE_BET365,
|
||||
EVENT_SOURCE_BWIN,
|
||||
EVENT_SOURCE_BETFAIR,
|
||||
EVENT_SOURCE_1XBET,
|
||||
EVENT_SOURCE_ENET:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func ParseEventSource(val string) (EventSource, error) {
|
||||
s := EventSource(val)
|
||||
if !s.IsValid() {
|
||||
return "", fmt.Errorf("invalid EventSource: %q", val)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type BaseEvent struct {
|
||||
ID int64
|
||||
SourceEventID string
|
||||
|
|
@ -67,6 +120,7 @@ type BaseEvent struct {
|
|||
StartTime time.Time
|
||||
Source EventSource
|
||||
Status EventStatus
|
||||
TotalOddOutcomes int64
|
||||
IsMonitored bool
|
||||
DefaultIsFeatured bool
|
||||
DefaultIsActive bool
|
||||
|
|
@ -96,6 +150,7 @@ type BaseEventRes struct {
|
|||
StartTime time.Time `json:"start_time"`
|
||||
Source EventSource `json:"source"`
|
||||
Status EventStatus `json:"status"`
|
||||
TotalOddOutcomes int64 `json:"total_odd_outcomes"`
|
||||
IsMonitored bool `json:"is_monitored"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
|
|
@ -125,10 +180,11 @@ type EventWithSettings struct {
|
|||
StartTime time.Time
|
||||
Source EventSource
|
||||
Status EventStatus
|
||||
TotalOddOutcomes int64
|
||||
IsMonitored bool
|
||||
IsFeatured bool
|
||||
IsActive bool
|
||||
WinningUpperLimit int32
|
||||
WinningUpperLimit int64
|
||||
DefaultIsFeatured bool
|
||||
DefaultIsActive bool
|
||||
DefaultWinningUpperLimit int64
|
||||
|
|
@ -178,10 +234,11 @@ type EventWithSettingsRes struct {
|
|||
StartTime time.Time `json:"start_time"`
|
||||
Source EventSource `json:"source"`
|
||||
Status EventStatus `json:"status"`
|
||||
TotalOddOutcomes int64 `json:"total_odd_outcomes"`
|
||||
IsMonitored bool `json:"is_monitored"`
|
||||
IsFeatured bool `json:"is_featured"`
|
||||
IsActive bool `json:"is_active"`
|
||||
WinningUpperLimit int32 `json:"winning_upper_limit"`
|
||||
WinningUpperLimit int64 `json:"winning_upper_limit"`
|
||||
DefaultIsFeatured bool `json:"default_is_featured"`
|
||||
DefaultIsActive bool `json:"default_is_active"`
|
||||
DefaultWinningUpperLimit int64 `json:"default_winning_upper_limit"`
|
||||
|
|
@ -204,12 +261,18 @@ type EventSettings struct {
|
|||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type CreateEventSettings struct {
|
||||
type UpdateTenantEventSettings struct {
|
||||
CompanyID int64
|
||||
EventID int64
|
||||
IsActive ValidBool
|
||||
IsFeatured ValidBool
|
||||
WinningUpperLimit ValidInt
|
||||
WinningUpperLimit ValidInt64
|
||||
}
|
||||
type UpdateGlobalEventSettings struct {
|
||||
EventID int64
|
||||
IsActive ValidBool
|
||||
IsFeatured ValidBool
|
||||
WinningUpperLimit ValidInt64
|
||||
}
|
||||
|
||||
type ValidEventStatus struct {
|
||||
|
|
@ -273,6 +336,7 @@ func ConvertDBEvent(event dbgen.EventWithCountry) BaseEvent {
|
|||
StartTime: event.StartTime.Time.UTC(),
|
||||
Source: EventSource(event.Source),
|
||||
Status: EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOutcomes,
|
||||
DefaultIsFeatured: event.DefaultIsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
DefaultIsActive: event.DefaultIsActive,
|
||||
|
|
@ -331,8 +395,8 @@ func ConvertCreateEvent(e CreateEvent) dbgen.InsertEventParams {
|
|||
}
|
||||
}
|
||||
|
||||
func ConvertCreateEventSettings(eventSettings CreateEventSettings) dbgen.SaveEventSettingsParams {
|
||||
return dbgen.SaveEventSettingsParams{
|
||||
func ConvertCreateEventSettings(eventSettings UpdateTenantEventSettings) dbgen.SaveTenantEventSettingsParams {
|
||||
return dbgen.SaveTenantEventSettingsParams{
|
||||
CompanyID: eventSettings.CompanyID,
|
||||
EventID: eventSettings.EventID,
|
||||
IsActive: eventSettings.IsActive.ToPG(),
|
||||
|
|
@ -344,6 +408,8 @@ func ConvertCreateEventSettings(eventSettings CreateEventSettings) dbgen.SaveEve
|
|||
func ConvertDBEventWithSetting(event dbgen.EventWithSetting) EventWithSettings {
|
||||
return EventWithSettings{
|
||||
ID: event.ID,
|
||||
SourceEventID: event.SourceEventID,
|
||||
WinningUpperLimit: event.WinningUpperLimit,
|
||||
SportID: event.SportID,
|
||||
MatchName: event.MatchName,
|
||||
HomeTeam: event.HomeTeam,
|
||||
|
|
@ -361,6 +427,7 @@ func ConvertDBEventWithSetting(event dbgen.EventWithSetting) EventWithSettings {
|
|||
StartTime: event.StartTime.Time.UTC(),
|
||||
Source: EventSource(event.Source),
|
||||
Status: EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOutcomes,
|
||||
IsFeatured: event.IsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
IsActive: event.IsActive,
|
||||
|
|
@ -401,8 +468,8 @@ func ConvertDBEventWithSettings(events []dbgen.EventWithSetting) []EventWithSett
|
|||
return result
|
||||
}
|
||||
|
||||
func ConvertUpdateEventSettings(event CreateEventSettings) dbgen.SaveEventSettingsParams {
|
||||
return dbgen.SaveEventSettingsParams{
|
||||
func ConvertUpdateTenantEventSettings(event UpdateTenantEventSettings) dbgen.SaveTenantEventSettingsParams {
|
||||
return dbgen.SaveTenantEventSettingsParams{
|
||||
EventID: event.EventID,
|
||||
CompanyID: event.CompanyID,
|
||||
IsActive: event.IsActive.ToPG(),
|
||||
|
|
@ -410,10 +477,19 @@ func ConvertUpdateEventSettings(event CreateEventSettings) dbgen.SaveEventSettin
|
|||
WinningUpperLimit: event.WinningUpperLimit.ToPG(),
|
||||
}
|
||||
}
|
||||
func ConvertUpdateGlobalEventSettings(event UpdateGlobalEventSettings) dbgen.UpdateGlobalEventSettingsParams {
|
||||
return dbgen.UpdateGlobalEventSettingsParams{
|
||||
ID: event.EventID,
|
||||
DefaultIsActive: event.IsActive.ToPG(),
|
||||
DefaultIsFeatured: event.IsFeatured.ToPG(),
|
||||
DefaultWinningUpperLimit: event.WinningUpperLimit.ToPG(),
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertEventRes(event BaseEvent) BaseEventRes {
|
||||
return BaseEventRes{
|
||||
ID: event.ID,
|
||||
SourceEventID: event.SourceEventID,
|
||||
SportID: event.SportID,
|
||||
MatchName: event.MatchName,
|
||||
HomeTeam: event.HomeTeam,
|
||||
|
|
@ -428,6 +504,7 @@ func ConvertEventRes(event BaseEvent) BaseEventRes {
|
|||
StartTime: event.StartTime.UTC(),
|
||||
Source: EventSource(event.Source),
|
||||
Status: EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOddOutcomes,
|
||||
DefaultIsFeatured: event.DefaultIsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
DefaultIsActive: event.DefaultIsActive,
|
||||
|
|
@ -452,6 +529,7 @@ func ConvertEventResList(events []BaseEvent) []BaseEventRes {
|
|||
func ConvertEventWitSettingRes(event EventWithSettings) EventWithSettingsRes {
|
||||
return EventWithSettingsRes{
|
||||
ID: event.ID,
|
||||
SourceEventID: event.SourceEventID,
|
||||
SportID: event.SportID,
|
||||
MatchName: event.MatchName,
|
||||
HomeTeam: event.HomeTeam,
|
||||
|
|
@ -466,6 +544,7 @@ func ConvertEventWitSettingRes(event EventWithSettings) EventWithSettingsRes {
|
|||
StartTime: event.StartTime.UTC(),
|
||||
Source: EventSource(event.Source),
|
||||
Status: EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOddOutcomes,
|
||||
IsFeatured: event.IsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
IsActive: event.IsActive,
|
||||
|
|
@ -480,6 +559,7 @@ func ConvertEventWitSettingRes(event EventWithSettings) EventWithSettingsRes {
|
|||
MatchPeriod: event.MatchPeriod.Value,
|
||||
IsLive: event.IsLive,
|
||||
FetchedAt: event.FetchedAt.UTC(),
|
||||
UpdatedAt: event.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,17 @@ type UpdateLeague struct {
|
|||
SportID ValidInt32 `json:"sport_id" example:"1"`
|
||||
}
|
||||
|
||||
type UpdateLeagueSettingsReq struct {
|
||||
IsFeatured *bool `json:"is_featured" example:"true"`
|
||||
IsActive *bool `json:"is_active" example:"true"`
|
||||
}
|
||||
|
||||
type UpdateGlobalLeagueSettings struct {
|
||||
ID int64
|
||||
DefaultIsActive ValidBool
|
||||
DefaultIsFeatured ValidBool
|
||||
}
|
||||
|
||||
type LeagueFilter struct {
|
||||
Query ValidString
|
||||
CountryCode ValidString
|
||||
|
|
@ -109,8 +120,8 @@ func ConvertCreateLeague(league CreateLeague) dbgen.InsertLeagueParams {
|
|||
}
|
||||
}
|
||||
|
||||
func ConvertCreateLeagueSettings(leagueSetting CreateLeagueSettings) dbgen.InsertLeagueSettingsParams {
|
||||
return dbgen.InsertLeagueSettingsParams{
|
||||
func ConvertCreateLeagueSettings(leagueSetting CreateLeagueSettings) dbgen.SaveLeagueSettingsParams {
|
||||
return dbgen.SaveLeagueSettingsParams{
|
||||
CompanyID: leagueSetting.CompanyID,
|
||||
LeagueID: leagueSetting.LeagueID,
|
||||
IsActive: leagueSetting.IsActive.ToPG(),
|
||||
|
|
@ -231,3 +242,11 @@ func ConvertBaseLeagueResList(leagues []BaseLeague) []BaseLeagueRes {
|
|||
|
||||
return result
|
||||
}
|
||||
|
||||
func ConvertUpdateGlobalLeagueSetting(league UpdateGlobalLeagueSettings) dbgen.UpdateGlobalLeagueSettingsParams {
|
||||
return dbgen.UpdateGlobalLeagueSettingsParams{
|
||||
ID: league.ID,
|
||||
IsActive: league.DefaultIsActive.ToPG(),
|
||||
IsFeatured: league.DefaultIsFeatured.ToPG(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ type Notification struct {
|
|||
Priority int `json:"priority,omitempty"`
|
||||
Version int `json:"-"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Image string `json:"image"`
|
||||
Metadata json.RawMessage `json:"metadata,omitempty"`
|
||||
}
|
||||
type CreateNotification struct {
|
||||
|
|
@ -97,6 +99,8 @@ type CreateNotification struct {
|
|||
DeliveryChannel DeliveryChannel `json:"delivery_channel,omitempty"`
|
||||
Payload NotificationPayload `json:"payload"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Metadata json.RawMessage `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type CreateOddMarket struct {
|
|||
MarketType string
|
||||
MarketName string
|
||||
MarketID int64
|
||||
NumberOfOutcomes int64
|
||||
UpdatedAt time.Time
|
||||
Odds []map[string]interface{}
|
||||
}
|
||||
|
|
@ -25,6 +26,7 @@ type OddMarket struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
RawOdds []json.RawMessage `json:"raw_odds"`
|
||||
FetchedAt time.Time `json:"fetched_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
|
|
@ -41,6 +43,7 @@ type OddMarketWithSettings struct {
|
|||
MarketName string `json:"market_name"`
|
||||
MarketCategory string `json:"market_category"`
|
||||
MarketID int64 `json:"market_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
RawOdds []json.RawMessage `json:"raw_odds"`
|
||||
FetchedAt time.Time `json:"fetched_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
|
|
@ -61,6 +64,11 @@ type CreateOddMarketSettings struct {
|
|||
CustomRawOdds []map[string]interface{}
|
||||
}
|
||||
|
||||
type UpdateGlobalOddMarketSettings struct {
|
||||
OddMarketID int64
|
||||
IsActive ValidBool
|
||||
}
|
||||
|
||||
type CustomOdd struct {
|
||||
OddID int64 `json:"odd_id"`
|
||||
OddValue float32 `json:"odd_value"`
|
||||
|
|
@ -72,6 +80,11 @@ type CreateOddMarketSettingsReq struct {
|
|||
CustomOdd []CustomOdd `json:"custom_odd,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateGlobalOddMarketSettingsReq struct {
|
||||
OddMarketID int64 `json:"odd_market_id"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
}
|
||||
|
||||
type RawOddsByMarketID struct {
|
||||
ID int64 `json:"id"`
|
||||
MarketName string `json:"market_name"`
|
||||
|
|
@ -86,6 +99,8 @@ type OddMarketFilter struct {
|
|||
Offset ValidInt32
|
||||
}
|
||||
type OddMarketWithEventFilter struct {
|
||||
Status ValidString
|
||||
IsLive ValidBool
|
||||
Limit ValidInt32
|
||||
Offset ValidInt32
|
||||
}
|
||||
|
|
@ -106,6 +121,7 @@ func ConvertDBOddMarket(oddMarket dbgen.OddsMarketWithEvent) (OddMarket, error)
|
|||
MarketName: oddMarket.MarketName,
|
||||
MarketCategory: oddMarket.MarketCategory,
|
||||
MarketID: oddMarket.MarketID,
|
||||
NumberOfOutcomes: oddMarket.NumberOfOutcomes,
|
||||
RawOdds: rawOdds,
|
||||
FetchedAt: oddMarket.FetchedAt.Time,
|
||||
ExpiresAt: oddMarket.ExpiresAt.Time,
|
||||
|
|
@ -141,6 +157,7 @@ func ConvertCreateOddMarket(oddMarket CreateOddMarket) (dbgen.InsertOddsMarketPa
|
|||
MarketName: oddMarket.MarketName,
|
||||
MarketCategory: oddMarket.MarketCategory,
|
||||
MarketID: oddMarket.MarketID,
|
||||
NumberOfOutcomes: oddMarket.NumberOfOutcomes,
|
||||
RawOdds: rawOddsBytes,
|
||||
FetchedAt: pgtype.Timestamp{Time: time.Now(), Valid: true},
|
||||
ExpiresAt: pgtype.Timestamp{Time: (time.Now()).Add(time.Hour), Valid: true},
|
||||
|
|
@ -176,6 +193,7 @@ func ConvertDBOddMarketWithSetting(oms dbgen.OddsMarketWithSetting) (OddMarketWi
|
|||
MarketName: oms.MarketName,
|
||||
MarketCategory: oms.MarketCategory,
|
||||
MarketID: oms.MarketID,
|
||||
NumberOfOutcomes: oms.NumberOfOutcomes,
|
||||
RawOdds: rawOdds,
|
||||
FetchedAt: oms.FetchedAt.Time,
|
||||
ExpiresAt: oms.ExpiresAt.Time,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ type Raffle struct {
|
|||
Name string
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
TicketLimit int32
|
||||
Type string
|
||||
Status string
|
||||
}
|
||||
|
|
@ -67,6 +68,7 @@ type CreateRaffle struct {
|
|||
CompanyID int32 `json:"company_id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
ExpiresAt *time.Time `json:"expires_at" validate:"required"`
|
||||
TicketLimit int32 `json:"ticket_limit" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
|
@ -48,6 +49,28 @@ const (
|
|||
OUTCOME_STATUS_ERROR OutcomeStatus = 5 //Half Win and Half Given Back
|
||||
)
|
||||
|
||||
func (o OutcomeStatus) IsValid() bool {
|
||||
switch o {
|
||||
case OUTCOME_STATUS_PENDING,
|
||||
OUTCOME_STATUS_WIN,
|
||||
OUTCOME_STATUS_LOSS,
|
||||
OUTCOME_STATUS_VOID,
|
||||
OUTCOME_STATUS_HALF,
|
||||
OUTCOME_STATUS_ERROR:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func ParseOutcomeStatus(val int) (OutcomeStatus, error) {
|
||||
o := OutcomeStatus(val)
|
||||
if !o.IsValid() {
|
||||
return 0, fmt.Errorf("invalid OutcomeStatus: %d", val)
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (o *OutcomeStatus) String() string {
|
||||
switch *o {
|
||||
case OUTCOME_STATUS_PENDING:
|
||||
|
|
@ -72,7 +95,6 @@ type ValidOutcomeStatus struct {
|
|||
Valid bool
|
||||
}
|
||||
|
||||
|
||||
func (v ValidOutcomeStatus) ToPG() pgtype.Int4 {
|
||||
return pgtype.Int4{
|
||||
Int32: int32(v.Value),
|
||||
|
|
@ -80,7 +102,6 @@ func (v ValidOutcomeStatus) ToPG() pgtype.Int4 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
type TimeStatus int32
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ type ShopBetDetail struct {
|
|||
CompanyID int64
|
||||
FullName string
|
||||
PhoneNumber string
|
||||
FastCode string
|
||||
CashoutID string
|
||||
CashedOut bool
|
||||
BetID int64
|
||||
|
|
@ -80,12 +81,13 @@ type ShopBetRes struct {
|
|||
CompanyID int64 `json:"company_id" example:"2"`
|
||||
FullName string `json:"full_name" example:"John"`
|
||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
FastCode string `json:"fast_code" example:"12SD1"`
|
||||
CashoutID string `json:"cashout_id" example:"21234"`
|
||||
CashedOut bool `json:"cashed_out" example:"false"`
|
||||
BetID int64 `json:"bet_id" example:"1"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes" example:"1"`
|
||||
Status OutcomeStatus `json:"status" example:"1"`
|
||||
Amount Currency `json:"amount"`
|
||||
Amount float32 `json:"amount"`
|
||||
Outcomes []BetOutcome `json:"outcomes"`
|
||||
TransactionVerified bool `json:"transaction_verified" example:"true"`
|
||||
UpdatedAt time.Time `json:"updated_at" example:"2025-04-08T12:00:00Z"`
|
||||
|
|
@ -111,12 +113,13 @@ func ConvertShopBetDetail(shopBet ShopBetDetail) ShopBetRes {
|
|||
CompanyID: shopBet.CompanyID,
|
||||
FullName: shopBet.FullName,
|
||||
PhoneNumber: shopBet.PhoneNumber,
|
||||
FastCode: shopBet.FastCode,
|
||||
CashoutID: shopBet.CashoutID,
|
||||
CashedOut: shopBet.CashedOut,
|
||||
BetID: shopBet.BetID,
|
||||
NumberOfOutcomes: shopBet.NumberOfOutcomes,
|
||||
Status: shopBet.Status,
|
||||
Amount: shopBet.Amount,
|
||||
Amount: shopBet.Amount.Float32(),
|
||||
Outcomes: shopBet.Outcomes,
|
||||
TransactionVerified: shopBet.TransactionVerified,
|
||||
UpdatedAt: shopBet.UpdatedAt,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWalletIDDuplicate = errors.New("there already exists user id with wallet_type")
|
||||
)
|
||||
|
||||
type Wallet struct {
|
||||
ID int64
|
||||
|
|
|
|||
|
|
@ -103,7 +103,10 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
|
|||
Query: filter.Query.ToPG(),
|
||||
CreatedBefore: filter.CreatedBefore.ToPG(),
|
||||
CreatedAfter: filter.CreatedAfter.ToPG(),
|
||||
Offset: filter.Offset.ToPG(),
|
||||
Offset: pgtype.Int4{
|
||||
Int32: int32(filter.Offset.Value * filter.Limit.Value),
|
||||
Valid: filter.Offset.Valid,
|
||||
},
|
||||
Limit: filter.Limit.ToPG(),
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -123,7 +126,7 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
|
|||
Query: filter.Query.ToPG(),
|
||||
CreatedBefore: filter.CreatedBefore.ToPG(),
|
||||
CreatedAfter: filter.CreatedAfter.ToPG(),
|
||||
});
|
||||
})
|
||||
|
||||
var result []domain.GetBet = make([]domain.GetBet, 0, len(bets))
|
||||
for _, bet := range bets {
|
||||
|
|
@ -275,6 +278,36 @@ func (s *Store) SettleWinningBet(ctx context.Context, betID int64, userID int64,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) GetBetOutcomeViewByEventID(ctx context.Context, eventID int64, filter domain.BetOutcomeViewFilter) ([]domain.BetOutcomeViewRes, int64, error) {
|
||||
|
||||
outcomes, err := s.queries.GetBetOutcomeViewByEventID(ctx, dbgen.GetBetOutcomeViewByEventIDParams{
|
||||
EventID: eventID,
|
||||
FilterStatus: filter.OutcomeStatus.ToPG(),
|
||||
CompanyID: filter.CompanyID.ToPG(),
|
||||
Offset: filter.Offset.ToPG(),
|
||||
Limit: filter.Limit.ToPG(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to get bet outcomes by event ID",
|
||||
zap.Int64("event_id", eventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
total, err := s.queries.TotalBetOutcomeViewByEventID(ctx, dbgen.TotalBetOutcomeViewByEventIDParams{
|
||||
EventID: eventID,
|
||||
FilterStatus: filter.OutcomeStatus.ToPG(),
|
||||
CompanyID: filter.CompanyID.ToPG(),
|
||||
})
|
||||
|
||||
var result []domain.BetOutcomeViewRes = make([]domain.BetOutcomeViewRes, 0, len(outcomes))
|
||||
for _, outcome := range outcomes {
|
||||
result = append(result, domain.ConvertDBBetOutcomesView(outcome))
|
||||
}
|
||||
return result, total, nil
|
||||
}
|
||||
func (s *Store) GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error) {
|
||||
|
||||
outcomes, err := s.queries.GetBetOutcomeByEventID(ctx, dbgen.GetBetOutcomeByEventIDParams{
|
||||
|
|
@ -377,6 +410,45 @@ func (s *Store) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int6
|
|||
}
|
||||
return result, nil
|
||||
}
|
||||
func (s *Store) UpdateBetOutcomeStatusForOddId(ctx context.Context, oddID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error) {
|
||||
outcomes, err := s.queries.UpdateBetOutcomeStatusForOddID(ctx, dbgen.UpdateBetOutcomeStatusForOddIDParams{
|
||||
OddID: oddID,
|
||||
Status: int32(status),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to update bet outcome status for oddID",
|
||||
zap.Int64("oddId", oddID),
|
||||
zap.Int32("status", int32(status)),
|
||||
zap.Error(err),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []domain.BetOutcome = make([]domain.BetOutcome, 0, len(outcomes))
|
||||
for _, outcome := range outcomes {
|
||||
result = append(result, domain.ConvertDBBetOutcomes(outcome))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) (error) {
|
||||
err := s.queries.BulkUpdateBetOutcomeStatusByOddIDs(ctx, dbgen.BulkUpdateBetOutcomeStatusByOddIDsParams{
|
||||
Status: int32(status),
|
||||
OddIds: oddID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to update bet outcome status for oddIDs",
|
||||
zap.Int64s("oddIds", oddID),
|
||||
zap.Int32("status", int32(status)),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error {
|
||||
err := s.queries.UpdateBetWithCashback(ctx, dbgen.UpdateBetWithCashbackParams{
|
||||
|
|
|
|||
|
|
@ -68,8 +68,11 @@ func (s *Store) GetAllBranches(ctx context.Context, filter domain.BranchFilter)
|
|||
return branches, nil
|
||||
}
|
||||
|
||||
func (s *Store) SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error) {
|
||||
dbBranches, err := s.queries.SearchBranchByName(ctx, pgtype.Text{String: name, Valid: true})
|
||||
func (s *Store) SearchBranchByName(ctx context.Context, name string, companyID domain.ValidInt64) ([]domain.BranchDetail, error) {
|
||||
dbBranches, err := s.queries.SearchBranchByName(ctx, dbgen.SearchBranchByNameParams{
|
||||
Column1: pgtype.Text{String: name, Valid: true},
|
||||
CompanyID: companyID.ToPG(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
12
internal/repository/common.go
Normal file
12
internal/repository/common.go
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
func IsUniqueViolation(err error) bool {
|
||||
var pgErr *pgconn.PgError
|
||||
return errors.As(err, &pgErr) && pgErr.Code == "23505"
|
||||
}
|
||||
|
|
@ -2,36 +2,34 @@ package repository
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) {
|
||||
baseSlug := helpers.GenerateSlug(company.Name)
|
||||
uniqueSlug := baseSlug
|
||||
i := 1
|
||||
// baseSlug := helpers.GenerateSlug(company.Name)
|
||||
// uniqueSlug := baseSlug
|
||||
// i := 1
|
||||
|
||||
for {
|
||||
_, err := s.queries.GetCompanyIDUsingSlug(ctx, uniqueSlug)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
// slug is unique
|
||||
break
|
||||
} else {
|
||||
// real DB error
|
||||
return domain.Company{}, err
|
||||
}
|
||||
}
|
||||
uniqueSlug = fmt.Sprintf("%s-%d", baseSlug, i)
|
||||
i++
|
||||
}
|
||||
// for {
|
||||
// _, err := s.queries.GetCompanyUsingSlug(ctx, uniqueSlug)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, pgx.ErrNoRows) {
|
||||
// // slug is unique
|
||||
// break
|
||||
// } else {
|
||||
// // real DB error
|
||||
// return domain.Company{}, err
|
||||
// }
|
||||
// }
|
||||
// uniqueSlug = fmt.Sprintf("%s-%d", baseSlug, i)
|
||||
// i++
|
||||
// }
|
||||
fmt.Printf("\ncompany %v\n\n", company)
|
||||
dbCompany, err := s.queries.CreateCompany(ctx, domain.ConvertCreateCompany(company))
|
||||
|
||||
dbCompany, err := s.queries.CreateCompany(ctx, domain.ConvertCreateCompany(company, uniqueSlug))
|
||||
if err != nil {
|
||||
return domain.Company{}, err
|
||||
}
|
||||
|
|
@ -78,25 +76,26 @@ func (s *Store) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany
|
|||
return domain.ConvertDBCompanyDetails(dbCompany), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetCompanyIDBySlug(ctx context.Context, slug string) (int64, error) {
|
||||
dbCompanyID, err := s.queries.GetCompanyIDUsingSlug(ctx, slug)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return dbCompanyID, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error) {
|
||||
dbCompany, err := s.queries.UpdateCompany(ctx, domain.ConvertUpdateCompany(company))
|
||||
func (s *Store) GetCompanyBySlug(ctx context.Context, slug string) (domain.Company, error) {
|
||||
dbCompany, err := s.queries.GetCompanyUsingSlug(ctx, slug)
|
||||
|
||||
if err != nil {
|
||||
return domain.Company{}, err
|
||||
}
|
||||
|
||||
return domain.ConvertDBCompany(dbCompany), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateCompany(ctx context.Context, company domain.UpdateCompany) error {
|
||||
fmt.Printf("company %v\n", company)
|
||||
err := s.queries.UpdateCompany(ctx, domain.ConvertUpdateCompany(company))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteCompany(ctx context.Context, id int64) error {
|
||||
return s.queries.DeleteCompany(ctx, id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,6 +302,71 @@ func (s *Store) GetAllEnetpulsePreoddsBettingOffers(ctx context.Context) ([]doma
|
|||
return offers, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetFixturesWithPreodds(ctx context.Context) ([]domain.EnetpulseFixtureWithPreodds, error) {
|
||||
dbRows, err := s.queries.GetFixturesWithPreodds(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use a map to group preodds by fixture
|
||||
fixtureMap := make(map[string]*domain.EnetpulseFixtureWithPreodds)
|
||||
|
||||
for _, row := range dbRows {
|
||||
// If fixture not yet in map, add it
|
||||
if _, exists := fixtureMap[row.FixtureID]; !exists {
|
||||
fixtureMap[row.FixtureID] = &domain.EnetpulseFixtureWithPreodds{
|
||||
FixtureID: row.FixtureID,
|
||||
FixtureApiID: row.FixtureID, // same alias used in query
|
||||
FixtureName: row.FixtureName,
|
||||
SportFk: row.SportFk,
|
||||
TournamentFk: row.TournamentFk.String,
|
||||
TournamentTemplateFk: row.TournamentTemplateFk.String,
|
||||
TournamentStageFk: row.TournamentStageFk.String,
|
||||
StartDate: row.StartDate.Time,
|
||||
StatusType: row.StatusType.String,
|
||||
StatusDescFk: row.StatusDescFk.String,
|
||||
RoundTypeFk: row.RoundTypeFk.String,
|
||||
UpdatesCount: row.FixtureUpdatesCount.Int32,
|
||||
LastUpdatedAt: row.FixtureLastUpdatedAt.Time,
|
||||
CreatedAt: row.FixtureCreatedAt.Time,
|
||||
UpdatedAt: row.FixtureUpdatedAt.Time,
|
||||
Preodds: []domain.EnetpulsePreodds{}, // initialize slice
|
||||
}
|
||||
}
|
||||
|
||||
// Add preodds only if it exists (avoid NULL rows)
|
||||
if row.PreoddsDbID.Valid {
|
||||
preodds := domain.EnetpulsePreodds{
|
||||
ID: row.PreoddsDbID.Int64,
|
||||
PreoddsID: row.PreoddsID.String,
|
||||
EventFK: row.EventFk.Int64,
|
||||
OutcomeTypeFK: row.OutcomeTypeFk.Int32,
|
||||
OutcomeScopeFK: row.OutcomeScopeFk.Int32,
|
||||
OutcomeSubtypeFK: row.OutcomeSubtypeFk.Int32,
|
||||
EventParticipantNumber: row.EventParticipantNumber.Int32,
|
||||
IParam: row.Iparam.String,
|
||||
IParam2: row.Iparam2.String,
|
||||
DParam: row.Dparam.String,
|
||||
DParam2: row.Dparam2.String,
|
||||
SParam: row.Sparam.String,
|
||||
UpdatesCount: row.PreoddsUpdatesCount.Int32,
|
||||
LastUpdatedAt: row.PreoddsLastUpdatedAt.Time,
|
||||
CreatedAt: row.PreoddsCreatedAt.Time,
|
||||
UpdatedAt: row.PreoddsUpdatedAt.Time,
|
||||
}
|
||||
fixtureMap[row.FixtureID].Preodds = append(fixtureMap[row.FixtureID].Preodds, preodds)
|
||||
}
|
||||
}
|
||||
|
||||
// Flatten the map into a slice
|
||||
result := make([]domain.EnetpulseFixtureWithPreodds, 0, len(fixtureMap))
|
||||
for _, f := range fixtureMap {
|
||||
result = append(result, *f)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// func ConvertCreateEnetpulseTournamentStage(stage domain.CreateEnetpulseTournamentStage) dbgen.EnetpulseTournamentStage {
|
||||
// return dbgen.EnetpulseTournamentStage{
|
||||
// StageID: stage.StageID,
|
||||
|
|
@ -356,14 +421,14 @@ func ConvertDBEnetpulseFixture(dbF dbgen.EnetpulseFixture) domain.EnetpulseFixtu
|
|||
TournamentTemplateName: dbF.TournamentTemplateName.String,
|
||||
SportName: dbF.SportName.String,
|
||||
Gender: dbF.Gender.String,
|
||||
StartDate: dbF.StartDate.Time,
|
||||
StartDate: dbF.StartDate.Time.String(),
|
||||
StatusType: dbF.StatusType.String,
|
||||
StatusDescFK: dbF.StatusDescFk.String,
|
||||
RoundTypeFK: dbF.RoundTypeFk.String,
|
||||
UpdatesCount: int(dbF.UpdatesCount.Int32),
|
||||
LastUpdatedAt: dbF.LastUpdatedAt.Time,
|
||||
CreatedAt: dbF.CreatedAt.Time,
|
||||
UpdatedAt: dbF.UpdatedAt.Time,
|
||||
UpdatesCount: fmt.Sprintf("%v", dbF.UpdatesCount),
|
||||
LastUpdatedAt: dbF.LastUpdatedAt.Time.String(),
|
||||
// CreatedAt: dbF.CreatedAt.Time,
|
||||
// UpdatedAt: dbF.UpdatedAt.Time,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -672,17 +737,17 @@ func ConvertCreateEnetpulsePreodds(p domain.CreateEnetpulsePreodds) (dbgen.Creat
|
|||
func ConvertDBEnetpulsePreodds(dbP dbgen.EnetpulsePreodd) domain.EnetpulsePreodds {
|
||||
return domain.EnetpulsePreodds{
|
||||
PreoddsID: dbP.PreoddsID,
|
||||
EventFK: fmt.Sprintf("%v", dbP.EventFk),
|
||||
OutcomeTypeFK: fmt.Sprintf("%v", dbP.OutcomeTypeFk),
|
||||
OutcomeScopeFK: fmt.Sprintf("%v", dbP.OutcomeScopeFk),
|
||||
OutcomeSubtypeFK: fmt.Sprintf("%v", dbP.OutcomeSubtypeFk),
|
||||
EventParticipantNumber: int(dbP.EventParticipantNumber.Int32),
|
||||
EventFK: dbP.EventFk,
|
||||
OutcomeTypeFK: dbP.OutcomeTypeFk.Int32,
|
||||
OutcomeScopeFK: dbP.OutcomeScopeFk.Int32,
|
||||
OutcomeSubtypeFK: dbP.OutcomeSubtypeFk.Int32,
|
||||
EventParticipantNumber: dbP.EventParticipantNumber.Int32,
|
||||
IParam: dbP.Iparam.String,
|
||||
IParam2: dbP.Iparam2.String,
|
||||
DParam: dbP.Dparam.String,
|
||||
DParam2: dbP.Dparam2.String,
|
||||
SParam: dbP.Sparam.String,
|
||||
UpdatesCount: int(dbP.UpdatesCount.Int32),
|
||||
UpdatesCount: dbP.UpdatesCount.Int32,
|
||||
LastUpdatedAt: dbP.LastUpdatedAt.Time,
|
||||
CreatedAt: dbP.CreatedAt.Time,
|
||||
UpdatedAt: dbP.UpdatedAt.Time,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package repository
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
|
|
@ -27,7 +26,11 @@ func (s *Store) GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]
|
|||
SportID: filter.SportID.ToPG(),
|
||||
Query: filter.Query.ToPG(),
|
||||
Limit: filter.Limit.ToPG(),
|
||||
Offset: filter.Offset.ToPG(),
|
||||
Offset: pgtype.Int4{
|
||||
Int32: int32(filter.Offset.Value * filter.Limit.Value),
|
||||
Valid: filter.Offset.Valid,
|
||||
},
|
||||
|
||||
FirstStartTime: filter.FirstStartTime.ToPG(),
|
||||
LastStartTime: filter.LastStartTime.ToPG(),
|
||||
CountryCode: filter.CountryCode.ToPG(),
|
||||
|
|
@ -55,8 +58,7 @@ func (s *Store) GetAllEvents(ctx context.Context, filter domain.EventFilter) ([]
|
|||
return nil, 0, err
|
||||
}
|
||||
|
||||
numberOfPages := math.Ceil(float64(totalCount) / float64(filter.Limit.Value))
|
||||
return domain.ConvertDBEvents(events), int64(numberOfPages), nil
|
||||
return domain.ConvertDBEvents(events), totalCount, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error) {
|
||||
|
|
@ -66,7 +68,10 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
|
|||
SportID: filter.SportID.ToPG(),
|
||||
Query: filter.Query.ToPG(),
|
||||
Limit: filter.Limit.ToPG(),
|
||||
Offset: filter.Offset.ToPG(),
|
||||
Offset: pgtype.Int4{
|
||||
Int32: int32(filter.Offset.Value * filter.Limit.Value),
|
||||
Valid: filter.Offset.Valid,
|
||||
},
|
||||
FirstStartTime: filter.FirstStartTime.ToPG(),
|
||||
LastStartTime: filter.LastStartTime.ToPG(),
|
||||
CountryCode: filter.CountryCode.ToPG(),
|
||||
|
|
@ -99,8 +104,6 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
|
|||
return nil, 0, err
|
||||
}
|
||||
|
||||
numberOfPages := math.Ceil(float64(totalCount) / float64(filter.Limit.Value))
|
||||
|
||||
result := make([]domain.EventWithSettings, len(events))
|
||||
|
||||
for i, event := range events {
|
||||
|
|
@ -123,6 +126,9 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
|
|||
StartTime: event.StartTime.Time.UTC(),
|
||||
Source: domain.EventSource(event.Source),
|
||||
Status: domain.EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOutcomes,
|
||||
SourceEventID: event.SourceEventID,
|
||||
WinningUpperLimit: event.WinningUpperLimit,
|
||||
IsFeatured: event.IsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
IsActive: event.IsActive,
|
||||
|
|
@ -155,7 +161,7 @@ func (s *Store) GetEventsWithSettings(ctx context.Context, companyID int64, filt
|
|||
}
|
||||
}
|
||||
|
||||
return result, int64(numberOfPages), nil
|
||||
return result, totalCount, nil
|
||||
}
|
||||
func (s *Store) GetEventByID(ctx context.Context, ID int64) (domain.BaseEvent, error) {
|
||||
event, err := s.queries.GetEventByID(ctx, ID)
|
||||
|
|
@ -204,6 +210,9 @@ func (s *Store) GetEventWithSettingByID(ctx context.Context, ID int64, companyID
|
|||
StartTime: event.StartTime.Time.UTC(),
|
||||
Source: domain.EventSource(event.Source),
|
||||
Status: domain.EventStatus(event.Status),
|
||||
TotalOddOutcomes: event.TotalOutcomes,
|
||||
SourceEventID: event.SourceEventID,
|
||||
WinningUpperLimit: event.WinningUpperLimit,
|
||||
IsFeatured: event.IsFeatured,
|
||||
IsMonitored: event.IsMonitored,
|
||||
IsActive: event.IsActive,
|
||||
|
|
@ -281,10 +290,13 @@ func (s *Store) UpdateEventMonitored(ctx context.Context, eventID int64, IsMonit
|
|||
})
|
||||
}
|
||||
|
||||
func (s *Store) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error {
|
||||
return s.queries.SaveEventSettings(ctx, domain.ConvertUpdateEventSettings(event))
|
||||
func (s *Store) UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error {
|
||||
return s.queries.SaveTenantEventSettings(ctx, domain.ConvertUpdateTenantEventSettings(event))
|
||||
}
|
||||
|
||||
func (s *Store) UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error {
|
||||
return s.queries.UpdateGlobalEventSettings(ctx, domain.ConvertUpdateGlobalEventSettings(event))
|
||||
}
|
||||
func (s *Store) DeleteEvent(ctx context.Context, eventID int64) error {
|
||||
err := s.queries.DeleteEvent(ctx, eventID)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ func (s *Store) SaveLeague(ctx context.Context, league domain.CreateLeague) erro
|
|||
}
|
||||
|
||||
func (s *Store) SaveLeagueSettings(ctx context.Context, leagueSettings domain.CreateLeagueSettings) error {
|
||||
return s.queries.InsertLeagueSettings(ctx, domain.ConvertCreateLeagueSettings(leagueSettings))
|
||||
return s.queries.SaveLeagueSettings(ctx, domain.ConvertCreateLeagueSettings(leagueSettings))
|
||||
}
|
||||
|
||||
func (s *Store) GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, error) {
|
||||
func (s *Store) GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague,int64, error) {
|
||||
l, err := s.queries.GetAllLeagues(ctx, dbgen.GetAllLeaguesParams{
|
||||
Query: filter.Query.ToPG(),
|
||||
CountryCode: filter.CountryCode.ToPG(),
|
||||
|
|
@ -31,10 +31,17 @@ func (s *Store) GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) (
|
|||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return domain.ConvertDBBaseLeagues(l), nil
|
||||
total, err := s.queries.GetTotalLeagues(ctx, dbgen.GetTotalLeaguesParams{
|
||||
Query: filter.Query.ToPG(),
|
||||
CountryCode: filter.CountryCode.ToPG(),
|
||||
SportID: filter.SportID.ToPG(),
|
||||
IsActive: filter.IsActive.ToPG(),
|
||||
})
|
||||
|
||||
return domain.ConvertDBBaseLeagues(l), total, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetAllLeaguesByCompany(ctx context.Context, companyID int64, filter domain.LeagueFilter) ([]domain.LeagueWithSettings, int64, error) {
|
||||
|
|
@ -85,3 +92,7 @@ func (s *Store) CheckLeagueSupport(ctx context.Context, leagueID int64, companyI
|
|||
func (s *Store) UpdateLeague(ctx context.Context, league domain.UpdateLeague) error {
|
||||
return s.queries.UpdateLeague(ctx, domain.ConvertUpdateLeague(league))
|
||||
}
|
||||
|
||||
func (s *Store) UpdateGlobalLeagueSettings(ctx context.Context, league domain.UpdateGlobalLeagueSettings) error {
|
||||
return s.queries.UpdateGlobalLeagueSettings(ctx, domain.ConvertUpdateGlobalLeagueSetting(league))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type NotificationRepository interface {
|
|||
CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error)
|
||||
GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error)
|
||||
GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error)
|
||||
DeleteOldNotifications(ctx context.Context) error
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
|
|
@ -69,6 +70,8 @@ func (r *Repository) CreateNotification(ctx context.Context, notification *domai
|
|||
Payload: marshalPayload(notification.Payload),
|
||||
Priority: priority,
|
||||
Timestamp: pgtype.Timestamptz{Time: notification.Timestamp, Valid: true},
|
||||
Expires: pgtype.Timestamptz{Time: notification.Expires, Valid: true},
|
||||
Img: pgtype.Text{String: notification.Image, Valid: notification.Image != ""},
|
||||
Metadata: notification.Metadata,
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +163,10 @@ func (r *Repository) ListRecipientIDs(ctx context.Context, receiver domain.Notif
|
|||
return r.store.queries.ListRecipientIDsByReceiver(ctx, string(receiver))
|
||||
}
|
||||
|
||||
func (s *Repository) DeleteOldNotifications(ctx context.Context) error {
|
||||
return s.store.queries.DeleteOldNotifications(ctx)
|
||||
}
|
||||
|
||||
func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification {
|
||||
var errorSeverity domain.NotificationErrorSeverity
|
||||
if dbNotif.ErrorSeverity.Valid {
|
||||
|
|
@ -199,6 +206,8 @@ func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notifica
|
|||
Payload: payload,
|
||||
Priority: priority,
|
||||
Timestamp: dbNotif.Timestamp.Time,
|
||||
Expires: dbNotif.Expires.Time,
|
||||
Image: dbNotif.Img.String,
|
||||
Metadata: dbNotif.Metadata,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ func (s *Store) GetOddsWithSettingsByMarketID(ctx context.Context, marketID int6
|
|||
MarketName: odds.MarketName,
|
||||
MarketCategory: odds.MarketCategory,
|
||||
MarketID: odds.MarketID,
|
||||
NumberOfOutcomes: odds.NumberOfOutcomes,
|
||||
RawOdds: rawOdds,
|
||||
FetchedAt: odds.FetchedAt.Time,
|
||||
ExpiresAt: odds.ExpiresAt.Time,
|
||||
|
|
@ -227,6 +228,7 @@ func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID
|
|||
MarketName: odds.MarketName,
|
||||
MarketCategory: odds.MarketCategory,
|
||||
MarketID: odds.MarketID,
|
||||
NumberOfOutcomes: odds.NumberOfOutcomes,
|
||||
RawOdds: rawOdds,
|
||||
FetchedAt: odds.FetchedAt.Time,
|
||||
ExpiresAt: odds.ExpiresAt.Time,
|
||||
|
|
@ -239,16 +241,10 @@ func (s *Store) GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID
|
|||
func (s *Store) GetOddsByEventID(ctx context.Context, eventID int64, filter domain.OddMarketWithEventFilter) ([]domain.OddMarket, error) {
|
||||
odds, err := s.queries.GetOddsByEventID(ctx, dbgen.GetOddsByEventIDParams{
|
||||
EventID: eventID,
|
||||
Status: filter.Status.ToPG(),
|
||||
IsLive: filter.IsLive.ToPG(),
|
||||
Limit: filter.Limit.ToPG(),
|
||||
Offset: filter.Offset.ToPG(),
|
||||
IsLive: pgtype.Bool{
|
||||
Bool: false,
|
||||
Valid: true,
|
||||
},
|
||||
Status: pgtype.Text{
|
||||
String: string(domain.STATUS_PENDING),
|
||||
Valid: true,
|
||||
},
|
||||
Source: pgtype.Text{},
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -299,6 +295,7 @@ func (s *Store) GetOddsWithSettingsByEventID(ctx context.Context, eventID int64,
|
|||
MarketName: o.MarketName,
|
||||
MarketCategory: o.MarketCategory,
|
||||
MarketID: o.MarketID,
|
||||
NumberOfOutcomes: o.NumberOfOutcomes,
|
||||
RawOdds: rawOdds,
|
||||
FetchedAt: o.FetchedAt.Time,
|
||||
ExpiresAt: o.ExpiresAt.Time,
|
||||
|
|
@ -322,3 +319,21 @@ func (s *Store) SaveOddsSetting(ctx context.Context, odd domain.CreateOddMarketS
|
|||
}
|
||||
return s.queries.SaveOddSettings(ctx, res)
|
||||
}
|
||||
|
||||
func (s *Store) UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error {
|
||||
return s.queries.UpdateGlobalOddsSetting(ctx, dbgen.UpdateGlobalOddsSettingParams{
|
||||
ID: odd.OddMarketID,
|
||||
DefaultIsActive: odd.IsActive.ToPG(),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) DeleteAllCompanyOddsSetting(ctx context.Context, companyID int64) error {
|
||||
return s.queries.DeleteAllCompanyOddsSetting(ctx, companyID)
|
||||
}
|
||||
|
||||
func (s *Store) DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error {
|
||||
return s.queries.DeleteCompanyOddsSettingByOddMarketID(ctx, dbgen.DeleteCompanyOddsSettingByOddMarketIDParams{
|
||||
CompanyID: companyID,
|
||||
OddsMarketID: oddMarketID,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ func convertRaffleOutcome(raffle dbgen.Raffle) domain.Raffle {
|
|||
Name: raffle.Name,
|
||||
CreatedAt: raffle.CreatedAt.Time,
|
||||
ExpiresAt: raffle.ExpiresAt.Time,
|
||||
TicketLimit: raffle.TicketLimit,
|
||||
Type: raffle.Type,
|
||||
Status: raffle.Status,
|
||||
}
|
||||
|
|
@ -48,6 +49,7 @@ func convertCreateRaffle(raffle domain.CreateRaffle) dbgen.CreateRaffleParams {
|
|||
Time: *raffle.ExpiresAt,
|
||||
Valid: true,
|
||||
},
|
||||
TicketLimit: raffle.TicketLimit,
|
||||
Type: raffle.Type,
|
||||
}
|
||||
}
|
||||
|
|
@ -191,3 +193,18 @@ func (s *Store) CheckValidSportRaffleFilter(ctx context.Context, raffleID int32,
|
|||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetRaffleTicketLimit(ctx context.Context, raffleID int32) (int32, error) {
|
||||
return s.queries.GetRaffleTicketLimit(ctx, raffleID)
|
||||
}
|
||||
|
||||
func (s *Store) GetRaffleTicketCount(ctx context.Context, raffleID, userID int32) (int64, error) {
|
||||
return s.queries.GetRaffleTicketCount(ctx, dbgen.GetRaffleTicketCountParams{
|
||||
RaffleID: raffleID,
|
||||
UserID: userID,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) CheckSportRaffleHasFilter(ctx context.Context, raffleID int32) (bool, error) {
|
||||
return s.queries.CheckSportRaffleHasFilter(ctx, raffleID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ func convertDBShopBetDetail(bet dbgen.ShopBetDetail) domain.ShopBetDetail {
|
|||
CompanyID: bet.CompanyID,
|
||||
FullName: bet.CustomerFullName,
|
||||
PhoneNumber: bet.CustomerPhoneNumber,
|
||||
FastCode: bet.FastCode,
|
||||
CashoutID: bet.CashoutID,
|
||||
CashedOut: bet.CashedOut,
|
||||
BetID: bet.BetID,
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ func (s *Store) GetAllUsers(ctx context.Context, filter domain.UserFilter) ([]do
|
|||
Valid: filter.PageSize.Valid,
|
||||
},
|
||||
Offset: pgtype.Int4{
|
||||
Int32: int32(filter.Page.Value),
|
||||
Int32: int32(filter.Page.Value * filter.PageSize.Value),
|
||||
Valid: filter.Page.Valid,
|
||||
},
|
||||
Query: pgtype.Text{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
|
|
@ -30,7 +29,7 @@ type VirtualGameRepository interface {
|
|||
RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error)
|
||||
|
||||
GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
// GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
GetUserGameHistory(ctx context.Context, userID int64) ([]domain.VirtualGameHistory, error)
|
||||
CreateVirtualGameHistory(ctx context.Context, his *domain.VirtualGameHistory) error
|
||||
|
||||
|
|
@ -255,36 +254,36 @@ func (r *VirtualGameRepo) UpdateVirtualGameTransactionStatus(ctx context.Context
|
|||
})
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
|
||||
query := `SELECT
|
||||
COUNT(*) as total,
|
||||
COUNT(CASE WHEN is_active = true THEN 1 END) as active,
|
||||
COUNT(CASE WHEN is_active = false THEN 1 END) as inactive
|
||||
FROM virtual_games`
|
||||
// func (r *VirtualGameRepo) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
|
||||
// query := `SELECT
|
||||
// COUNT(*) as total,
|
||||
// COUNT(CASE WHEN is_active = true THEN 1 END) as active,
|
||||
// COUNT(CASE WHEN is_active = false THEN 1 END) as inactive
|
||||
// FROM virtual_games`
|
||||
|
||||
args := []interface{}{}
|
||||
argPos := 1
|
||||
// args := []interface{}{}
|
||||
// argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.StartTime.Valid {
|
||||
query += fmt.Sprintf(" WHERE created_at >= $%d", argPos)
|
||||
args = append(args, filter.StartTime.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.EndTime.Valid {
|
||||
query += fmt.Sprintf(" AND created_at <= $%d", argPos)
|
||||
args = append(args, filter.EndTime.Value)
|
||||
argPos++
|
||||
}
|
||||
// // Add filters if provided
|
||||
// if filter.StartTime.Valid {
|
||||
// query += fmt.Sprintf(" WHERE created_at >= $%d", argPos)
|
||||
// args = append(args, filter.StartTime.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.EndTime.Valid {
|
||||
// query += fmt.Sprintf(" AND created_at <= $%d", argPos)
|
||||
// args = append(args, filter.EndTime.Value)
|
||||
// argPos++
|
||||
// }
|
||||
|
||||
row := r.store.conn.QueryRow(ctx, query, args...)
|
||||
err = row.Scan(&total, &active, &inactive)
|
||||
if err != nil {
|
||||
return 0, 0, 0, fmt.Errorf("failed to get game counts: %w", err)
|
||||
}
|
||||
// row := r.store.conn.QueryRow(ctx, query, args...)
|
||||
// err = row.Scan(&total, &active, &inactive)
|
||||
// if err != nil {
|
||||
// return 0, 0, 0, fmt.Errorf("failed to get game counts: %w", err)
|
||||
// }
|
||||
|
||||
return total, active, inactive, nil
|
||||
}
|
||||
// return total, active, inactive, nil
|
||||
// }
|
||||
|
||||
func (r *VirtualGameRepo) GetUserGameHistory(ctx context.Context, userID int64) ([]domain.VirtualGameHistory, error) {
|
||||
query := `SELECT game_id FROM virtual_game_histories WHERE user_id = $1 AND transaction_type = 'BET' ORDER BY created_at DESC LIMIT 100`
|
||||
|
|
@ -315,4 +314,3 @@ func (r *VirtualGameRepo) ListAllVirtualGames(ctx context.Context, arg dbgen.Get
|
|||
func (r *VirtualGameRepo) RemoveAllVirtualGames(ctx context.Context) error {
|
||||
return r.store.queries.DeleteAllVirtualGames(ctx)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ func convertDBGetCustomerWallet(customerWallet dbgen.CustomerWalletDetail) domai
|
|||
func (s *Store) CreateWallet(ctx context.Context, wallet domain.CreateWallet) (domain.Wallet, error) {
|
||||
newWallet, err := s.queries.CreateWallet(ctx, convertCreateWallet(wallet))
|
||||
if err != nil {
|
||||
if IsUniqueViolation(err) {
|
||||
return domain.Wallet{}, domain.ErrWalletIDDuplicate
|
||||
}
|
||||
return domain.Wallet{}, err
|
||||
}
|
||||
return convertDBWallet(newWallet), nil
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ func (s *Service) SendAdminErrorNotification(ctx context.Context, betID int64, s
|
|||
for _, user := range users {
|
||||
for _, channel := range []domain.DeliveryChannel{
|
||||
domain.DeliveryChannelInApp,
|
||||
domain.DeliveryChannelEmail,
|
||||
// domain.DeliveryChannelEmail,
|
||||
} {
|
||||
n := newBetResultNotification(user.ID, domain.NotificationLevelError, channel, headline, message, map[string]any{
|
||||
"status": status,
|
||||
|
|
@ -247,7 +247,7 @@ func (s *Service) SendAdminErrorNotification(ctx context.Context, betID int64, s
|
|||
}
|
||||
func (s *Service) SendAdminLargeBetNotification(ctx context.Context, betID int64, totalWinnings float32, extra string, companyID int64) error {
|
||||
|
||||
headline := fmt.Sprintf("SYSTEM WARNING: High Risk Bet", betID, totalWinnings)
|
||||
headline := "SYSTEM WARNING: High Risk Bet"
|
||||
message := fmt.Sprintf("Bet #%d has been created with %v payout", betID, totalWinnings)
|
||||
|
||||
super_admin_users, _, err := s.userSvc.GetAllUsers(ctx, domain.UserFilter{
|
||||
|
|
@ -283,7 +283,7 @@ func (s *Service) SendAdminLargeBetNotification(ctx context.Context, betID int64
|
|||
for _, user := range users {
|
||||
for _, channel := range []domain.DeliveryChannel{
|
||||
domain.DeliveryChannelInApp,
|
||||
domain.DeliveryChannelEmail,
|
||||
// domain.DeliveryChannelEmail,
|
||||
} {
|
||||
raw, _ := json.Marshal(map[string]any{
|
||||
"winnings": totalWinnings,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ type BetStore interface {
|
|||
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, int64, error)
|
||||
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
|
||||
GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, error)
|
||||
GetBetOutcomeViewByEventID(ctx context.Context, eventID int64, filter domain.BetOutcomeViewFilter) ([]domain.BetOutcomeViewRes, int64, error)
|
||||
GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
|
||||
GetBetOutcomeByBetID(ctx context.Context, betID int64) ([]domain.BetOutcome, error)
|
||||
GetBetOutcomeCountByOddID(ctx context.Context, oddID int64) (int64, error)
|
||||
|
|
@ -25,7 +26,8 @@ type BetStore interface {
|
|||
UpdateBetOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
||||
UpdateBetOutcomeStatusByBetID(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
||||
UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error)
|
||||
|
||||
UpdateBetOutcomeStatusForOddId(ctx context.Context, oddID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error)
|
||||
BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) error
|
||||
GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
||||
totalStakes domain.Currency,
|
||||
totalBets int64,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ var (
|
|||
ErrGenerateRandomOutcome = errors.New("failed to generate any random outcome for events")
|
||||
ErrOutcomesNotCompleted = errors.New("some bet outcomes are still pending")
|
||||
ErrEventHasBeenRemoved = errors.New("event has been removed")
|
||||
ErrEventHasBeenDisabled = errors.New("event has been disabled")
|
||||
|
||||
ErrEventHasNotEnded = errors.New("event has not ended yet")
|
||||
ErrOddHasBeenDisabled = errors.New("odd has been disabled")
|
||||
ErrRawOddInvalid = errors.New("prematch Raw Odd is Invalid")
|
||||
ErrBranchIDRequired = errors.New("branch ID required for this role")
|
||||
ErrOutcomeLimit = errors.New("too many outcomes on a single bet")
|
||||
|
|
@ -46,6 +48,8 @@ var (
|
|||
ErrInvalidAmount = errors.New("invalid amount")
|
||||
ErrBetAmountTooHigh = errors.New("cannot create a bet with an amount above limit")
|
||||
ErrBetWinningTooHigh = errors.New("total Winnings over set limit")
|
||||
|
||||
ErrCompanyDeductedPercentInvalid = errors.New("invalid company deducted percentage")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
|
@ -106,10 +110,10 @@ func (s *Service) GenerateCashoutID() (string, error) {
|
|||
return string(result), nil
|
||||
}
|
||||
|
||||
func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketID int64, oddID int64) (domain.CreateBetOutcome, error) {
|
||||
func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketID int64, oddID int64, companyID int64) (domain.CreateBetOutcome, error) {
|
||||
oddIDStr := strconv.FormatInt(oddID, 10)
|
||||
|
||||
event, err := s.eventSvc.GetEventByID(ctx, eventID)
|
||||
event, err := s.eventSvc.GetEventWithSettingByID(ctx, eventID, companyID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to fetch upcoming event by ID",
|
||||
zap.Int64("event_id", eventID),
|
||||
|
|
@ -118,6 +122,14 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
|
|||
return domain.CreateBetOutcome{}, ErrEventHasBeenRemoved
|
||||
}
|
||||
|
||||
if !event.IsActive {
|
||||
s.mongoLogger.Warn("attempting to create bet with disabled event",
|
||||
zap.Int64("event_id", eventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetOutcome{}, ErrEventHasBeenDisabled
|
||||
}
|
||||
|
||||
currentTime := time.Now()
|
||||
if event.StartTime.Before(currentTime) {
|
||||
s.mongoLogger.Error("event has already started",
|
||||
|
|
@ -128,7 +140,7 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
|
|||
return domain.CreateBetOutcome{}, ErrEventHasNotEnded
|
||||
}
|
||||
|
||||
odds, err := s.prematchSvc.GetOddsByMarketID(ctx, marketID, eventID)
|
||||
odds, err := s.prematchSvc.GetOddsWithSettingsByMarketID(ctx, marketID, eventID, companyID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get raw odds by market ID",
|
||||
zap.Int64("event_id", eventID),
|
||||
|
|
@ -138,6 +150,15 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
|
|||
return domain.CreateBetOutcome{}, err
|
||||
}
|
||||
|
||||
if !odds.IsActive {
|
||||
s.mongoLogger.Error("failed to get raw odds by market ID",
|
||||
zap.Int64("event_id", eventID),
|
||||
zap.Int64("market_id", marketID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetOutcome{}, ErrOddHasBeenDisabled
|
||||
}
|
||||
|
||||
type rawOddType struct {
|
||||
ID string
|
||||
Name string
|
||||
|
|
@ -255,7 +276,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
var totalOdds float32 = 1
|
||||
|
||||
for _, outcomeReq := range req.Outcomes {
|
||||
newOutcome, err := s.GenerateBetOutcome(ctx, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID)
|
||||
newOutcome, err := s.GenerateBetOutcome(ctx, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID, companyID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to generate outcome",
|
||||
zap.Int64("event_id", outcomeReq.EventID),
|
||||
|
|
@ -303,8 +324,9 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
}
|
||||
|
||||
fastCode := helpers.GenerateFastCode()
|
||||
accumulator := calculateAccumulator(len(outcomes))
|
||||
amount := req.Amount + (req.Amount * accumulator)
|
||||
// accumulator := calculateAccumulator(len(outcomes))
|
||||
// amount := req.Amount + (req.Amount * accumulator)
|
||||
amount := req.Amount
|
||||
|
||||
newBet := domain.CreateBet{
|
||||
Amount: domain.ToCurrency(amount),
|
||||
|
|
@ -524,7 +546,27 @@ func (s *Service) DeductBetFromBranchWallet(ctx context.Context, amount float32,
|
|||
return err
|
||||
}
|
||||
|
||||
if company.DeductedPercentage > 1 {
|
||||
s.mongoLogger.Error("Invalid company deducted percentage",
|
||||
zap.Int64("wallet_id", walletID),
|
||||
zap.Float32("amount", company.DeductedPercentage),
|
||||
zap.Error(err),
|
||||
)
|
||||
return ErrCompanyDeductedPercentInvalid
|
||||
}
|
||||
|
||||
// This is the amount that we take from a company/tenant when they
|
||||
// create a bet. I.e. if its 5% (0.05), then thats the percentage we take every
|
||||
deductedAmount := amount * company.DeductedPercentage
|
||||
|
||||
if deductedAmount == 0 {
|
||||
s.mongoLogger.Fatal("Amount",
|
||||
zap.Int64("wallet_id", walletID),
|
||||
zap.Float32("amount", deductedAmount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx,
|
||||
walletID, domain.ToCurrency(deductedAmount), domain.ValidInt64{
|
||||
Value: userID,
|
||||
|
|
@ -848,6 +890,9 @@ func (s *Service) GetBetOutcomeByBetID(ctx context.Context, UserID int64) ([]dom
|
|||
return s.betStore.GetBetOutcomeByBetID(ctx, UserID)
|
||||
}
|
||||
|
||||
func (s *Service) GetBetOutcomeViewByEventID(ctx context.Context, eventID int64, filter domain.BetOutcomeViewFilter) ([]domain.BetOutcomeViewRes, int64, error) {
|
||||
return s.betStore.GetBetOutcomeViewByEventID(ctx, eventID, filter)
|
||||
}
|
||||
func (s *Service) GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error) {
|
||||
return s.betStore.GetBetOutcomeByEventID(ctx, eventID, is_filtered)
|
||||
}
|
||||
|
|
@ -1076,6 +1121,32 @@ func (s *Service) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID in
|
|||
return outcomes, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateBetOutcomeStatusForOddId(ctx context.Context, oddID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error) {
|
||||
outcomes, err := s.betStore.UpdateBetOutcomeStatusForOddId(ctx, oddID, status)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to update bet outcome status",
|
||||
zap.Int64("oddID", oddID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return outcomes, nil
|
||||
}
|
||||
|
||||
func (s *Service) BulkUpdateBetOutcomeStatusForOddIds(ctx context.Context, oddID []int64, status domain.OutcomeStatus) error {
|
||||
err := s.betStore.BulkUpdateBetOutcomeStatusForOddIds(ctx, oddID, status)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to update bet outcome status by oddIds",
|
||||
zap.Int64s("oddID", oddID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SetBetToRemoved(ctx context.Context, id int64) error {
|
||||
_, err := s.betStore.UpdateBetOutcomeStatusByBetID(ctx, id, domain.OUTCOME_STATUS_VOID)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type BranchStore interface {
|
|||
GetBranchByManagerID(ctx context.Context, branchManagerID int64) ([]domain.BranchDetail, error)
|
||||
GetBranchByCompanyID(ctx context.Context, companyID int64) ([]domain.BranchDetail, error)
|
||||
GetAllBranches(ctx context.Context, filter domain.BranchFilter) ([]domain.BranchDetail, error)
|
||||
SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error)
|
||||
SearchBranchByName(ctx context.Context, name string, companyID domain.ValidInt64) ([]domain.BranchDetail, error)
|
||||
UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error)
|
||||
DeleteBranch(ctx context.Context, id int64) error
|
||||
CreateBranchOperation(ctx context.Context, branchOperation domain.CreateBranchOperation) error
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ func (s *Service) GetAllSupportedOperations(ctx context.Context) ([]domain.Suppo
|
|||
return s.branchStore.GetAllSupportedOperations(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) SearchBranchByName(ctx context.Context, name string) ([]domain.BranchDetail, error) {
|
||||
return s.branchStore.SearchBranchByName(ctx, name)
|
||||
func (s *Service) SearchBranchByName(ctx context.Context, name string, companyID domain.ValidInt64) ([]domain.BranchDetail, error) {
|
||||
return s.branchStore.SearchBranchByName(ctx, name, companyID)
|
||||
}
|
||||
func (s *Service) UpdateBranch(ctx context.Context, branch domain.UpdateBranch) (domain.Branch, error) {
|
||||
return s.branchStore.UpdateBranch(ctx, branch)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ type CompanyStore interface {
|
|||
GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error)
|
||||
SearchCompanyByName(ctx context.Context, name string) ([]domain.GetCompany, error)
|
||||
GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error)
|
||||
GetCompanyIDBySlug(ctx context.Context, slug string) (int64, error)
|
||||
UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error)
|
||||
GetCompanyBySlug(ctx context.Context, slug string) (domain.Company, error)
|
||||
UpdateCompany(ctx context.Context, company domain.UpdateCompany) (error)
|
||||
DeleteCompany(ctx context.Context, id int64) error
|
||||
|
||||
GetCompanyCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@ func (s *Service) GetAllCompanies(ctx context.Context, filter domain.CompanyFilt
|
|||
func (s *Service) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany, error) {
|
||||
return s.companyStore.GetCompanyByID(ctx, id)
|
||||
}
|
||||
func (s *Service) GetCompanyIDBySlug(ctx context.Context, slug string) (int64, error){
|
||||
return s.companyStore.GetCompanyIDBySlug(ctx, slug)
|
||||
func (s *Service) GetCompanyBySlug(ctx context.Context, slug string) (domain.Company, error) {
|
||||
return s.companyStore.GetCompanyBySlug(ctx, slug)
|
||||
}
|
||||
|
||||
func (s *Service) SearchCompanyByName(ctx context.Context, name string) ([]domain.GetCompany, error) {
|
||||
return s.companyStore.SearchCompanyByName(ctx, name)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error) {
|
||||
func (s *Service) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (error) {
|
||||
return s.companyStore.UpdateCompany(ctx, company)
|
||||
}
|
||||
func (s *Service) DeleteCompany(ctx context.Context, id int64) error {
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ func (s *Service) FetchAndStoreTournamentTemplates(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Println("✅ Successfully fetched and stored all tournament templates")
|
||||
// fmt.Println("✅ Successfully fetched and stored all tournament templates")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -367,7 +367,7 @@ func (s *Service) FetchAndStoreTournamentStages(ctx context.Context) error {
|
|||
for _, t := range tournaments {
|
||||
// Compose URL for each tournament
|
||||
url := fmt.Sprintf(
|
||||
"http://eapi.enetpulse.com/tournament_stage/list/?language_typeFK=3&tz=Europe/Sofia&tournamentFK=%s&username=%s&token=%s",
|
||||
"https://eapi.enetpulse.com/tournament_stage/list/?language_typeFK=3&tz=Europe/Sofia&tournamentFK=%s&username=%s&token=%s",
|
||||
t.TournamentID,
|
||||
s.cfg.EnetPulseConfig.UserName,
|
||||
s.cfg.EnetPulseConfig.Token,
|
||||
|
|
@ -460,125 +460,13 @@ func (s *Service) GetAllTournamentStages(ctx context.Context) ([]domain.Enetpuls
|
|||
}
|
||||
|
||||
func (s *Service) FetchAndStoreFixtures(ctx context.Context, date string) error {
|
||||
// 1️⃣ Fetch all sports from the database
|
||||
// 1️⃣ Fetch all sports from DB
|
||||
sports, err := s.store.GetAllEnetpulseSports(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch sports from DB: %w", err)
|
||||
}
|
||||
|
||||
// Struct for decoding each fixture from API
|
||||
type Fixture struct {
|
||||
FixtureID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SportFK string `json:"sportFK"`
|
||||
TournamentFK string `json:"tournamentFK"`
|
||||
TournamentName string `json:"tournament_name"`
|
||||
StartDate string `json:"startdate"`
|
||||
StatusType string `json:"status_type"`
|
||||
HomeTeam string `json:"home_team"`
|
||||
AwayTeam string `json:"away_team"`
|
||||
HomeTeamID string `json:"home_team_id"`
|
||||
AwayTeamID string `json:"away_team_id"`
|
||||
HomeKitImage string `json:"home_kit_image"`
|
||||
AwayKitImage string `json:"away_kit_image"`
|
||||
}
|
||||
|
||||
// 2️⃣ Loop through each sport
|
||||
for _, sport := range sports {
|
||||
if sport.SportID != "1" {
|
||||
continue
|
||||
}
|
||||
|
||||
url := fmt.Sprintf(
|
||||
"http://eapi.enetpulse.com/event/fixtures/?username=%s&token=%s&sportFK=%s&language_typeFK=3&date=%s",
|
||||
s.cfg.EnetPulseConfig.UserName,
|
||||
s.cfg.EnetPulseConfig.Token,
|
||||
sport.SportID,
|
||||
date,
|
||||
)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("creating fixtures request for sport %s: %v\n", sport.SportID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
fmt.Printf("requesting fixtures for sport %s: %v\n", sport.SportID, err)
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
fmt.Printf("failed to fetch fixtures for sport %s (status %d): %s\n",
|
||||
sport.SportID, resp.StatusCode, string(body))
|
||||
continue
|
||||
}
|
||||
|
||||
// 3️⃣ Decode API response
|
||||
var fixturesResp struct {
|
||||
Events map[string]Fixture `json:"events"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&fixturesResp); err != nil {
|
||||
fmt.Printf("decoding fixtures response for sport %s: %v\n", sport.SportID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 4️⃣ Iterate over fixtures and store as events
|
||||
for _, fx := range fixturesResp.Events {
|
||||
// Conversions
|
||||
sportID, _ := strconv.Atoi(fx.SportFK)
|
||||
homeTeamID, _ := strconv.ParseInt(fx.HomeTeamID, 10, 64)
|
||||
awayTeamID, _ := strconv.ParseInt(fx.AwayTeamID, 10, 64)
|
||||
leagueID, _ := strconv.ParseInt(fx.TournamentFK, 10, 64)
|
||||
startDate, _ := time.Parse("2006-01-02 15:04:05", fx.StartDate)
|
||||
|
||||
event := domain.CreateEvent{
|
||||
SourceEventID: fx.FixtureID,
|
||||
SportID: int32(sportID),
|
||||
MatchName: fx.Name,
|
||||
HomeTeam: fx.HomeTeam,
|
||||
AwayTeam: fx.AwayTeam,
|
||||
HomeTeamID: homeTeamID,
|
||||
AwayTeamID: awayTeamID,
|
||||
HomeTeamImage: fx.HomeKitImage,
|
||||
AwayTeamImage: fx.AwayKitImage,
|
||||
LeagueID: leagueID,
|
||||
LeagueName: fx.TournamentName,
|
||||
StartTime: startDate,
|
||||
IsLive: false, // default, can update later from live feed
|
||||
Status: domain.STATUS_PENDING, // map to enum if needed
|
||||
Source: "EnetPulse", // custom enum constant
|
||||
DefaultWinningUpperLimit: 0, // default, can adjust
|
||||
}
|
||||
|
||||
// 5️⃣ Save event in DB (UPSERT)
|
||||
if err := s.store.SaveEvent(ctx, event); err != nil {
|
||||
fmt.Printf("failed storing event %s: %v\n", fx.FixtureID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Successfully fetched and stored events for sport %s\n", sport.SportID)
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Println("✅ Completed fetching and storing events for all sports")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.EnetpulseFixture, error) {
|
||||
var allFixtures []domain.EnetpulseFixture
|
||||
|
||||
// 1️⃣ Fetch all sports from the database
|
||||
sports, err := s.store.GetAllEnetpulseSports(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch sports from DB: %w", err)
|
||||
}
|
||||
|
||||
// Struct for decoding each fixture from API
|
||||
// Define API fixture struct
|
||||
type Fixture struct {
|
||||
FixtureID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
|
@ -591,23 +479,22 @@ func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.Enet
|
|||
TournamentTemplateName string `json:"tournament_template_name"`
|
||||
SportName string `json:"sport_name"`
|
||||
Gender string `json:"gender"`
|
||||
StartDate string `json:"startdate"`
|
||||
StartDate string `json:"startdate"` // ISO 8601
|
||||
StatusType string `json:"status_type"`
|
||||
StatusDescFK string `json:"status_descFK"`
|
||||
RoundTypeFK string `json:"round_typeFK"`
|
||||
UpdatesCount string `json:"n"`
|
||||
LastUpdatedAt string `json:"ut"`
|
||||
UpdatesCount string `json:"n"` // convert to int
|
||||
LastUpdatedAt string `json:"ut"` // parse to time.Time
|
||||
}
|
||||
|
||||
// 2️⃣ Loop through each sport
|
||||
for _, sport := range sports {
|
||||
// Only fetch for sport "1" (Football)
|
||||
if sport.SportID != "1" {
|
||||
continue
|
||||
}
|
||||
|
||||
url := fmt.Sprintf(
|
||||
"http://eapi.enetpulse.com/event/fixtures/?username=%s&token=%s&sportFK=%s&language_typeFK=3&date=%s",
|
||||
"https://eapi.enetpulse.com/event/fixtures/?username=%s&token=%s&sportFK=%s&language_typeFK=3&date=%s",
|
||||
s.cfg.EnetPulseConfig.UserName,
|
||||
s.cfg.EnetPulseConfig.Token,
|
||||
sport.SportID,
|
||||
|
|
@ -616,7 +503,7 @@ func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.Enet
|
|||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("creating fixtures request for sport %s: %v\n", sport.SportID, err)
|
||||
fmt.Printf("creating request for sport %s: %v\n", sport.SportID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -639,29 +526,38 @@ func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.Enet
|
|||
Events map[string]Fixture `json:"events"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&fixturesResp); err != nil {
|
||||
fmt.Printf("decoding fixtures response for sport %s: %v\n", sport.SportID, err)
|
||||
fmt.Printf("decoding fixtures for sport %s: %v\n", sport.SportID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 4️⃣ Iterate over fixtures and store them
|
||||
// 4️⃣ Iterate and upsert fixtures
|
||||
for _, fx := range fixturesResp.Events {
|
||||
tournamentFK, _ := strconv.Atoi(fx.TournamentFK)
|
||||
tournamentTemplateFK, _ := strconv.Atoi(fx.TournamentTemplateFK)
|
||||
tournamentStageFK, _ := strconv.Atoi(fx.TournamentStageFK)
|
||||
statusDescFK, _ := strconv.Atoi(fx.StatusDescFK)
|
||||
roundTypeFK, _ := strconv.Atoi(fx.RoundTypeFK)
|
||||
updatesCount, _ := strconv.Atoi(fx.UpdatesCount)
|
||||
// Parse StartDate and LastUpdatedAt
|
||||
startDate, err := time.Parse(time.RFC3339, fx.StartDate)
|
||||
if err != nil {
|
||||
fmt.Printf("invalid startDate for fixture %s: %v\n", fx.FixtureID, err)
|
||||
continue
|
||||
}
|
||||
lastUpdated, err := time.Parse(time.RFC3339, fx.LastUpdatedAt)
|
||||
if err != nil {
|
||||
fmt.Printf("invalid lastUpdatedAt for fixture %s: %v\n", fx.FixtureID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
startDate, _ := time.Parse(time.RFC3339, fx.StartDate)
|
||||
lastUpdatedAt, _ := time.Parse(time.RFC3339, fx.LastUpdatedAt)
|
||||
// Convert UpdatesCount
|
||||
updatesCount, err := strconv.Atoi(fx.UpdatesCount)
|
||||
if err != nil {
|
||||
fmt.Printf("invalid updatesCount for fixture %s: %v\n", fx.FixtureID, err)
|
||||
updatesCount = 0
|
||||
}
|
||||
|
||||
createFixture := domain.CreateEnetpulseFixture{
|
||||
fixture := domain.CreateEnetpulseFixture{
|
||||
FixtureID: fx.FixtureID,
|
||||
Name: fx.Name,
|
||||
SportFK: fx.SportFK,
|
||||
TournamentFK: strconv.Itoa(tournamentFK),
|
||||
TournamentTemplateFK: strconv.Itoa(tournamentTemplateFK),
|
||||
TournamentStageFK: strconv.Itoa(tournamentStageFK),
|
||||
TournamentFK: fx.TournamentFK,
|
||||
TournamentTemplateFK: fx.TournamentTemplateFK,
|
||||
TournamentStageFK: fx.TournamentStageFK,
|
||||
TournamentStageName: fx.TournamentStageName,
|
||||
TournamentName: fx.TournamentName,
|
||||
TournamentTemplateName: fx.TournamentTemplateName,
|
||||
|
|
@ -669,29 +565,150 @@ func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.Enet
|
|||
Gender: fx.Gender,
|
||||
StartDate: startDate,
|
||||
StatusType: fx.StatusType,
|
||||
StatusDescFK: strconv.Itoa(statusDescFK),
|
||||
RoundTypeFK: strconv.Itoa(roundTypeFK),
|
||||
StatusDescFK: fx.StatusDescFK,
|
||||
RoundTypeFK: fx.RoundTypeFK,
|
||||
UpdatesCount: updatesCount,
|
||||
LastUpdatedAt: lastUpdatedAt,
|
||||
LastUpdatedAt: lastUpdated,
|
||||
}
|
||||
|
||||
dbFixture, err := s.store.CreateEnetpulseFixture(ctx, createFixture)
|
||||
if err != nil {
|
||||
fmt.Printf("failed storing fixture %s: %v\n", fx.FixtureID, err)
|
||||
// 5️⃣ Save fixture using UPSERT repository method
|
||||
if _, err := s.store.CreateEnetpulseFixture(ctx, fixture); err != nil {
|
||||
fmt.Printf("failed upserting fixture %s: %v\n", fx.FixtureID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
allFixtures = append(allFixtures, dbFixture)
|
||||
}
|
||||
|
||||
fmt.Printf("✅ Successfully fetched and stored fixtures for sport %s\n", sport.SportID)
|
||||
break // stop after first relevant sport
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Println("✅ Completed fetching and storing fixtures for all sports")
|
||||
return allFixtures, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// func (s *Service) FetchFixtures(ctx context.Context, date string) ([]domain.EnetpulseFixture, error) {
|
||||
// var allFixtures []domain.EnetpulseFixture
|
||||
|
||||
// // 1️⃣ Fetch all sports from the database
|
||||
// sports, err := s.store.GetAllEnetpulseSports(ctx)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to fetch sports from DB: %w", err)
|
||||
// }
|
||||
|
||||
// // Struct for decoding each fixture from API
|
||||
// type Fixture struct {
|
||||
// FixtureID string `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// SportFK string `json:"sportFK"`
|
||||
// TournamentFK string `json:"tournamentFK"`
|
||||
// TournamentTemplateFK string `json:"tournament_templateFK"`
|
||||
// TournamentStageFK string `json:"tournament_stageFK"`
|
||||
// TournamentStageName string `json:"tournament_stage_name"`
|
||||
// TournamentName string `json:"tournament_name"`
|
||||
// TournamentTemplateName string `json:"tournament_template_name"`
|
||||
// SportName string `json:"sport_name"`
|
||||
// Gender string `json:"gender"`
|
||||
// StartDate string `json:"startdate"`
|
||||
// StatusType string `json:"status_type"`
|
||||
// StatusDescFK string `json:"status_descFK"`
|
||||
// RoundTypeFK string `json:"round_typeFK"`
|
||||
// UpdatesCount string `json:"n"`
|
||||
// LastUpdatedAt string `json:"ut"`
|
||||
// }
|
||||
|
||||
// // 2️⃣ Loop through each sport
|
||||
// for _, sport := range sports {
|
||||
// // Only fetch for sport "1" (Football)
|
||||
// if sport.SportID != "1" {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// url := fmt.Sprintf(
|
||||
// "http://eapi.enetpulse.com/event/fixtures/?username=%s&token=%s&sportFK=%s&language_typeFK=3&date=%s",
|
||||
// s.cfg.EnetPulseConfig.UserName,
|
||||
// s.cfg.EnetPulseConfig.Token,
|
||||
// sport.SportID,
|
||||
// date,
|
||||
// )
|
||||
|
||||
// req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
// if err != nil {
|
||||
// fmt.Printf("creating fixtures request for sport %s: %v\n", sport.SportID, err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// resp, err := s.httpClient.Do(req)
|
||||
// if err != nil {
|
||||
// fmt.Printf("requesting fixtures for sport %s: %v\n", sport.SportID, err)
|
||||
// continue
|
||||
// }
|
||||
// defer resp.Body.Close()
|
||||
|
||||
// if resp.StatusCode != http.StatusOK {
|
||||
// body, _ := io.ReadAll(resp.Body)
|
||||
// fmt.Printf("failed to fetch fixtures for sport %s (status %d): %s\n",
|
||||
// sport.SportID, resp.StatusCode, string(body))
|
||||
// continue
|
||||
// }
|
||||
|
||||
// // 3️⃣ Decode API response
|
||||
// var fixturesResp struct {
|
||||
// Events map[string]Fixture `json:"events"`
|
||||
// }
|
||||
// if err := json.NewDecoder(resp.Body).Decode(&fixturesResp); err != nil {
|
||||
// fmt.Printf("decoding fixtures response for sport %s: %v\n", sport.SportID, err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// // 4️⃣ Iterate over fixtures and store them
|
||||
// for _, fx := range fixturesResp.Events {
|
||||
// tournamentFK, _ := strconv.Atoi(fx.TournamentFK)
|
||||
// tournamentTemplateFK, _ := strconv.Atoi(fx.TournamentTemplateFK)
|
||||
// tournamentStageFK, _ := strconv.Atoi(fx.TournamentStageFK)
|
||||
// statusDescFK, _ := strconv.Atoi(fx.StatusDescFK)
|
||||
// roundTypeFK, _ := strconv.Atoi(fx.RoundTypeFK)
|
||||
// updatesCount, _ := strconv.Atoi(fx.UpdatesCount)
|
||||
|
||||
// startDate, _ := time.Parse(time.RFC3339, fx.StartDate)
|
||||
// lastUpdatedAt, _ := time.Parse(time.RFC3339, fx.LastUpdatedAt)
|
||||
|
||||
// createFixture := domain.CreateEnetpulseFixture{
|
||||
// FixtureID: fx.FixtureID,
|
||||
// Name: fx.Name,
|
||||
// SportFK: fx.SportFK,
|
||||
// TournamentFK: strconv.Itoa(tournamentFK),
|
||||
// TournamentTemplateFK: strconv.Itoa(tournamentTemplateFK),
|
||||
// TournamentStageFK: strconv.Itoa(tournamentStageFK),
|
||||
// TournamentStageName: fx.TournamentStageName,
|
||||
// TournamentName: fx.TournamentName,
|
||||
// TournamentTemplateName: fx.TournamentTemplateName,
|
||||
// SportName: fx.SportName,
|
||||
// Gender: fx.Gender,
|
||||
// StartDate: startDate,
|
||||
// StatusType: fx.StatusType,
|
||||
// StatusDescFK: strconv.Itoa(statusDescFK),
|
||||
// RoundTypeFK: strconv.Itoa(roundTypeFK),
|
||||
// UpdatesCount: updatesCount,
|
||||
// LastUpdatedAt: lastUpdatedAt,
|
||||
// }
|
||||
|
||||
// dbFixture, err := s.store.CreateEnetpulseFixture(ctx, createFixture)
|
||||
// if err != nil {
|
||||
// fmt.Printf("failed storing fixture %s: %v\n", fx.FixtureID, err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// allFixtures = append(allFixtures, dbFixture)
|
||||
// }
|
||||
|
||||
// // fmt.Printf("✅ Successfully fetched and stored fixtures for sport %s\n", sport.SportID)
|
||||
// break // stop after first relevant sport
|
||||
// }
|
||||
|
||||
// // fmt.Println("✅ Completed fetching and storing fixtures for all sports")
|
||||
// return allFixtures, nil
|
||||
// }
|
||||
|
||||
func (s *Service) GetAllFixtures(ctx context.Context) ([]domain.EnetpulseFixture, error) {
|
||||
// 1️⃣ Fetch all from store
|
||||
fixtures, err := s.store.GetAllEnetpulseFixtures(ctx)
|
||||
|
|
@ -955,27 +972,33 @@ func (s *Service) GetAllOutcomeTypes(ctx context.Context) ([]domain.EnetpulseOut
|
|||
}
|
||||
|
||||
func (s *Service) FetchAndStorePreodds(ctx context.Context) error {
|
||||
// 1️⃣ Fetch all events from DB
|
||||
// 1️⃣ Fetch all fixtures
|
||||
fixtures, err := s.store.GetAllEnetpulseFixtures(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch fixtures: %w", err)
|
||||
}
|
||||
|
||||
// providerIDStr := strconv.Itoa(int(s.cfg.EnetPulseConfig.ProviderID))
|
||||
// 2️⃣ Fetch all outcome types
|
||||
outcomeTypes, err := s.store.GetAllEnetpulseOutcomeTypes(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch outcome types: %w", err)
|
||||
}
|
||||
|
||||
// 2️⃣ Loop through each fixture/event
|
||||
// 3️⃣ Loop through each fixture
|
||||
for _, fixture := range fixtures {
|
||||
// 4️⃣ Loop through each outcome type
|
||||
for _, outcome := range outcomeTypes {
|
||||
url := fmt.Sprintf(
|
||||
"http://eapi.enetpulse.com/preodds/event/?objectFK=%s&odds_providerFK=%s&username=%s&token=%s",
|
||||
"http://eapi.enetpulse.com/preodds/event/?objectFK=%s&odds_providerFK=%s&outcome_typeFK=%s&username=%s&token=%s",
|
||||
fixture.FixtureID,
|
||||
s.cfg.EnetPulseConfig.ProviderID,
|
||||
outcome.OutcomeTypeID,
|
||||
s.cfg.EnetPulseConfig.UserName,
|
||||
s.cfg.EnetPulseConfig.Token,
|
||||
)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
// optionally log error and continue to next fixture
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -989,7 +1012,6 @@ func (s *Service) FetchAndStorePreodds(ctx context.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
// Decode API response
|
||||
var preoddsResp struct {
|
||||
Preodds map[string]struct {
|
||||
ID string `json:"id"`
|
||||
|
|
@ -1022,7 +1044,6 @@ func (s *Service) FetchAndStorePreodds(ctx context.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
// Iterate and store preodds and nested betting offers
|
||||
for _, p := range preoddsResp.Preodds {
|
||||
updatesCount := 0
|
||||
if p.N != "" {
|
||||
|
|
@ -1043,7 +1064,7 @@ func (s *Service) FetchAndStorePreodds(ctx context.Context) error {
|
|||
createPreodds := domain.CreateEnetpulsePreodds{
|
||||
PreoddsID: p.ID,
|
||||
EventFK: fixture.FixtureID,
|
||||
OutcomeTypeFK: string(p.OutcomeTypeFK),
|
||||
OutcomeTypeFK: outcome.OutcomeTypeID,
|
||||
OutcomeScopeFK: string(p.OutcomeScopeFK),
|
||||
OutcomeSubtypeFK: string(p.OutcomeSubtypeFK),
|
||||
EventParticipantNumber: int(eventParticipantNumber),
|
||||
|
|
@ -1088,6 +1109,7 @@ func (s *Service) FetchAndStorePreodds(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1208,6 +1230,16 @@ func (s *Service) GetAllBettingOffers(ctx context.Context) ([]domain.EnetpulsePr
|
|||
return offers, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFixturesWithPreodds(ctx context.Context) ([]domain.EnetpulseFixtureWithPreodds, error) {
|
||||
// 1️⃣ Fetch fixtures and their associated preodds from the repository
|
||||
fixtures, err := s.store.GetFixturesWithPreodds(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch fixtures with preodds from DB: %w", err)
|
||||
}
|
||||
|
||||
return fixtures, nil
|
||||
}
|
||||
|
||||
// helper to safely parse string to int32
|
||||
// func parseStringToInt32(s string) int32 {
|
||||
// if s == "" {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ type Service interface {
|
|||
UpdateEventMonitored(ctx context.Context, eventID int64, IsMonitored bool) error
|
||||
GetEventsWithSettings(ctx context.Context, companyID int64, filter domain.EventFilter) ([]domain.EventWithSettings, int64, error)
|
||||
GetEventWithSettingByID(ctx context.Context, ID int64, companyID int64) (domain.EventWithSettings, error)
|
||||
UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error
|
||||
UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error
|
||||
UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error
|
||||
GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -491,8 +491,11 @@ func (s *service) GetEventWithSettingByID(ctx context.Context, ID int64, company
|
|||
return s.store.GetEventWithSettingByID(ctx, ID, companyID)
|
||||
}
|
||||
|
||||
func (s *service) UpdateEventSettings(ctx context.Context, event domain.CreateEventSettings) error {
|
||||
return s.store.UpdateEventSettings(ctx, event)
|
||||
func (s *service) UpdateTenantEventSettings(ctx context.Context, event domain.UpdateTenantEventSettings) error {
|
||||
return s.store.UpdateTenantEventSettings(ctx, event)
|
||||
}
|
||||
func (s *service) UpdateGlobalEventSettings(ctx context.Context, event domain.UpdateGlobalEventSettings) error {
|
||||
return s.store.UpdateGlobalEventSettings(ctx, event)
|
||||
}
|
||||
|
||||
func (s *service) GetSportAndLeagueIDs(ctx context.Context, eventID int64) ([]int64, error) {
|
||||
|
|
|
|||
|
|
@ -1,67 +1,67 @@
|
|||
package kafka
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
// import (
|
||||
// "context"
|
||||
// "encoding/json"
|
||||
// "log"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
||||
"github.com/segmentio/kafka-go"
|
||||
)
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
||||
// "github.com/segmentio/kafka-go"
|
||||
// )
|
||||
|
||||
type WalletConsumer struct {
|
||||
reader *kafka.Reader
|
||||
hub *ws.NotificationHub
|
||||
topic string
|
||||
groupID string
|
||||
brokers []string
|
||||
}
|
||||
// type WalletConsumer struct {
|
||||
// reader *kafka.Reader
|
||||
// hub *ws.NotificationHub
|
||||
// topic string
|
||||
// groupID string
|
||||
// brokers []string
|
||||
// }
|
||||
|
||||
func NewWalletConsumer(brokers []string, topic, groupID string, hub *ws.NotificationHub) *WalletConsumer {
|
||||
return &WalletConsumer{
|
||||
brokers: brokers,
|
||||
topic: topic,
|
||||
groupID: groupID,
|
||||
hub: hub,
|
||||
reader: kafka.NewReader(kafka.ReaderConfig{
|
||||
Brokers: brokers,
|
||||
GroupID: groupID,
|
||||
Topic: topic,
|
||||
}),
|
||||
}
|
||||
}
|
||||
// func NewWalletConsumer(brokers []string, topic, groupID string, hub *ws.NotificationHub) *WalletConsumer {
|
||||
// return &WalletConsumer{
|
||||
// brokers: brokers,
|
||||
// topic: topic,
|
||||
// groupID: groupID,
|
||||
// hub: hub,
|
||||
// reader: kafka.NewReader(kafka.ReaderConfig{
|
||||
// Brokers: brokers,
|
||||
// GroupID: groupID,
|
||||
// Topic: topic,
|
||||
// }),
|
||||
// }
|
||||
// }
|
||||
|
||||
func (c *WalletConsumer) Start(ctx context.Context) {
|
||||
go func() {
|
||||
for {
|
||||
m, err := c.reader.ReadMessage(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Error reading wallet Kafka message: %v", err)
|
||||
continue
|
||||
}
|
||||
// func (c *WalletConsumer) Start(ctx context.Context) {
|
||||
// go func() {
|
||||
// for {
|
||||
// m, err := c.reader.ReadMessage(ctx)
|
||||
// if err != nil {
|
||||
// log.Printf("Error reading wallet Kafka message: %v", err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
var evt event.WalletEvent
|
||||
if err := json.Unmarshal(m.Value, &evt); err != nil {
|
||||
log.Printf("Failed to unmarshal wallet event: %v", err)
|
||||
continue
|
||||
}
|
||||
// var evt event.WalletEvent
|
||||
// if err := json.Unmarshal(m.Value, &evt); err != nil {
|
||||
// log.Printf("Failed to unmarshal wallet event: %v", err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
payload := map[string]interface{}{
|
||||
"type": evt.EventType,
|
||||
"wallet_id": evt.WalletID,
|
||||
"user_id": evt.UserID,
|
||||
"balance": evt.Balance,
|
||||
"wallet_type": evt.WalletType,
|
||||
"trigger": evt.Trigger,
|
||||
"recipient_id": evt.UserID,
|
||||
}
|
||||
// payload := map[string]interface{}{
|
||||
// "type": evt.EventType,
|
||||
// "wallet_id": evt.WalletID,
|
||||
// "user_id": evt.UserID,
|
||||
// "balance": evt.Balance,
|
||||
// "wallet_type": evt.WalletType,
|
||||
// "trigger": evt.Trigger,
|
||||
// "recipient_id": evt.UserID,
|
||||
// }
|
||||
|
||||
// Broadcast to appropriate WebSocket clients
|
||||
c.hub.Broadcast <- payload
|
||||
}
|
||||
}()
|
||||
}
|
||||
// // Broadcast to appropriate WebSocket clients
|
||||
// c.hub.Broadcast <- payload
|
||||
// }
|
||||
// }()
|
||||
// }
|
||||
|
||||
// func (c *WalletConsumer) Shutdown() error {
|
||||
// return c.reader.Close()
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
package kafka
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
// import (
|
||||
// "context"
|
||||
// "encoding/json"
|
||||
// "time"
|
||||
|
||||
"github.com/segmentio/kafka-go"
|
||||
)
|
||||
// "github.com/segmentio/kafka-go"
|
||||
// )
|
||||
|
||||
type Producer struct {
|
||||
writer *kafka.Writer
|
||||
}
|
||||
// type Producer struct {
|
||||
// writer *kafka.Writer
|
||||
// }
|
||||
|
||||
func NewProducer(brokers []string, topic string) *Producer {
|
||||
return &Producer{
|
||||
writer: &kafka.Writer{
|
||||
Addr: kafka.TCP(brokers...),
|
||||
Topic: topic,
|
||||
Balancer: &kafka.LeastBytes{},
|
||||
},
|
||||
}
|
||||
}
|
||||
// func NewProducer(brokers []string, topic string) *Producer {
|
||||
// return &Producer{
|
||||
// writer: &kafka.Writer{
|
||||
// Addr: kafka.TCP(brokers...),
|
||||
// Topic: topic,
|
||||
// Balancer: &kafka.LeastBytes{},
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
||||
func (p *Producer) Publish(ctx context.Context, key string, event any) error {
|
||||
msgBytes, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// func (p *Producer) Publish(ctx context.Context, key string, event any) error {
|
||||
// msgBytes, err := json.Marshal(event)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
return p.writer.WriteMessages(ctx, kafka.Message{
|
||||
Key: []byte(key),
|
||||
Value: msgBytes,
|
||||
Time: time.Now(),
|
||||
})
|
||||
}
|
||||
// return p.writer.WriteMessages(ctx, kafka.Message{
|
||||
// Key: []byte(key),
|
||||
// Value: msgBytes,
|
||||
// Time: time.Now(),
|
||||
// })
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ import (
|
|||
type Service interface {
|
||||
SaveLeague(ctx context.Context, league domain.CreateLeague) error
|
||||
SaveLeagueSettings(ctx context.Context, leagueSettings domain.CreateLeagueSettings) error
|
||||
GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, error)
|
||||
GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, int64, error)
|
||||
GetAllLeaguesByCompany(ctx context.Context, companyID int64, filter domain.LeagueFilter) ([]domain.LeagueWithSettings, int64, error)
|
||||
CheckLeagueSupport(ctx context.Context, leagueID int64, companyID int64) (bool, error)
|
||||
UpdateLeague(ctx context.Context, league domain.UpdateLeague) error
|
||||
UpdateGlobalLeagueSettings(ctx context.Context, league domain.UpdateGlobalLeagueSettings) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ func (s *service) SaveLeagueSettings(ctx context.Context, leagueSettings domain.
|
|||
return s.store.SaveLeagueSettings(ctx, leagueSettings)
|
||||
}
|
||||
|
||||
func (s *service) GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, error) {
|
||||
func (s *service) GetAllLeagues(ctx context.Context, filter domain.LeagueFilter) ([]domain.BaseLeague, int64, error) {
|
||||
return s.store.GetAllLeagues(ctx, filter)
|
||||
}
|
||||
|
||||
|
|
@ -40,3 +40,7 @@ func (s *service) CheckLeagueSupport(ctx context.Context, leagueID int64, compan
|
|||
func (s *service) UpdateLeague(ctx context.Context, league domain.UpdateLeague) error {
|
||||
return s.store.UpdateLeague(ctx, league)
|
||||
}
|
||||
|
||||
func (s *service) UpdateGlobalLeagueSettings(ctx context.Context, league domain.UpdateGlobalLeagueSettings) error {
|
||||
return s.store.UpdateGlobalLeagueSettings(ctx, league)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package notificationservice
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
// "errors"
|
||||
|
|
@ -12,19 +11,19 @@ import (
|
|||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/messenger"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
"github.com/segmentio/kafka-go"
|
||||
// "github.com/segmentio/kafka-go"
|
||||
"go.uber.org/zap"
|
||||
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
||||
// afro "github.com/amanuelabay/afrosms-go"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/redis/go-redis/v9"
|
||||
// "github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
|
@ -39,8 +38,6 @@ type Service struct {
|
|||
messengerSvc *messenger.Service
|
||||
mongoLogger *zap.Logger
|
||||
logger *slog.Logger
|
||||
redisClient *redis.Client
|
||||
reader *kafka.Reader
|
||||
}
|
||||
|
||||
func New(repo repository.NotificationRepository,
|
||||
|
|
@ -49,17 +46,8 @@ func New(repo repository.NotificationRepository,
|
|||
cfg *config.Config,
|
||||
messengerSvc *messenger.Service,
|
||||
userSvc *user.Service,
|
||||
kafkaBrokers []string,
|
||||
) *Service {
|
||||
hub := ws.NewNotificationHub()
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: cfg.RedisAddr, // e.g., "redis:6379"
|
||||
})
|
||||
walletReader := kafka.NewReader(kafka.ReaderConfig{
|
||||
Brokers: kafkaBrokers,
|
||||
Topic: "wallet-balance-topic",
|
||||
GroupID: "notification-service-group", // Each service should have its own group
|
||||
})
|
||||
|
||||
svc := &Service{
|
||||
repo: repo,
|
||||
|
|
@ -72,15 +60,13 @@ func New(repo repository.NotificationRepository,
|
|||
messengerSvc: messengerSvc,
|
||||
userSvc: userSvc,
|
||||
config: cfg,
|
||||
redisClient: rdb,
|
||||
reader: walletReader,
|
||||
}
|
||||
|
||||
go hub.Run()
|
||||
go svc.startWorker()
|
||||
go svc.startRetryWorker()
|
||||
go svc.RunRedisSubscriber(context.Background())
|
||||
go svc.StartKafkaConsumer(context.Background())
|
||||
// go svc.RunRedisSubscriber(context.Background())
|
||||
// go svc.StartKafkaConsumer(context.Background())
|
||||
|
||||
return svc
|
||||
}
|
||||
|
|
@ -484,189 +470,192 @@ func (s *Service) CountUnreadNotifications(ctx context.Context, recipient_id int
|
|||
return s.repo.CountUnreadNotifications(ctx, recipient_id)
|
||||
}
|
||||
|
||||
func (s *Service) DeleteOldNotifications(ctx context.Context) error {
|
||||
return s.repo.DeleteOldNotifications(ctx)
|
||||
}
|
||||
|
||||
// func (s *Service) GetNotificationCounts(ctx context.Context, filter domain.ReportFilter) (total, read, unread int64, err error){
|
||||
// return s.repo.Get(ctx, filter)
|
||||
// }
|
||||
|
||||
func (s *Service) RunRedisSubscriber(ctx context.Context) {
|
||||
pubsub := s.redisClient.Subscribe(ctx, "live_metrics")
|
||||
defer pubsub.Close()
|
||||
// func (s *Service) RunRedisSubscriber(ctx context.Context) {
|
||||
// pubsub := s.redisClient.Subscribe(ctx, "live_metrics")
|
||||
// defer pubsub.Close()
|
||||
|
||||
ch := pubsub.Channel()
|
||||
for msg := range ch {
|
||||
var parsed map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(msg.Payload), &parsed); err != nil {
|
||||
// s.logger.Error("invalid Redis message format", "payload", msg.Payload, "error", err)
|
||||
s.mongoLogger.Error("invalid Redis message format",
|
||||
zap.String("payload", msg.Payload),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
continue
|
||||
}
|
||||
// ch := pubsub.Channel()
|
||||
// for msg := range ch {
|
||||
// var parsed map[string]interface{}
|
||||
// if err := json.Unmarshal([]byte(msg.Payload), &parsed); err != nil {
|
||||
// // s.logger.Error("invalid Redis message format", "payload", msg.Payload, "error", err)
|
||||
// s.mongoLogger.Error("invalid Redis message format",
|
||||
// zap.String("payload", msg.Payload),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// continue
|
||||
// }
|
||||
|
||||
eventType, _ := parsed["type"].(string)
|
||||
payload := parsed["payload"]
|
||||
recipientID, hasRecipient := parsed["recipient_id"]
|
||||
recipientType, _ := parsed["recipient_type"].(string)
|
||||
// eventType, _ := parsed["type"].(string)
|
||||
// payload := parsed["payload"]
|
||||
// recipientID, hasRecipient := parsed["recipient_id"]
|
||||
// recipientType, _ := parsed["recipient_type"].(string)
|
||||
|
||||
message := map[string]interface{}{
|
||||
"type": eventType,
|
||||
"payload": payload,
|
||||
}
|
||||
// message := map[string]interface{}{
|
||||
// "type": eventType,
|
||||
// "payload": payload,
|
||||
// }
|
||||
|
||||
if hasRecipient {
|
||||
message["recipient_id"] = recipientID
|
||||
message["recipient_type"] = recipientType
|
||||
}
|
||||
// if hasRecipient {
|
||||
// message["recipient_id"] = recipientID
|
||||
// message["recipient_type"] = recipientType
|
||||
// }
|
||||
|
||||
s.Hub.Broadcast <- message
|
||||
}
|
||||
}
|
||||
// s.Hub.Broadcast <- message
|
||||
// }
|
||||
// }
|
||||
|
||||
func (s *Service) UpdateLiveWalletMetrics(ctx context.Context, companies []domain.GetCompany, branches []domain.BranchWallet) error {
|
||||
const key = "live_metrics"
|
||||
// func (s *Service) UpdateLiveWalletMetrics(ctx context.Context, companies []domain.GetCompany, branches []domain.BranchWallet) error {
|
||||
// const key = "live_metrics"
|
||||
|
||||
companyBalances := make([]domain.CompanyWalletBalance, 0, len(companies))
|
||||
for _, c := range companies {
|
||||
companyBalances = append(companyBalances, domain.CompanyWalletBalance{
|
||||
CompanyID: c.ID,
|
||||
CompanyName: c.Name,
|
||||
Balance: float64(c.WalletBalance.Float32()),
|
||||
})
|
||||
}
|
||||
// companyBalances := make([]domain.CompanyWalletBalance, 0, len(companies))
|
||||
// for _, c := range companies {
|
||||
// companyBalances = append(companyBalances, domain.CompanyWalletBalance{
|
||||
// CompanyID: c.ID,
|
||||
// CompanyName: c.Name,
|
||||
// Balance: float64(c.WalletBalance.Float32()),
|
||||
// })
|
||||
// }
|
||||
|
||||
branchBalances := make([]domain.BranchWalletBalance, 0, len(branches))
|
||||
for _, b := range branches {
|
||||
branchBalances = append(branchBalances, domain.BranchWalletBalance{
|
||||
BranchID: b.ID,
|
||||
BranchName: b.Name,
|
||||
CompanyID: b.CompanyID,
|
||||
Balance: float64(b.Balance.Float32()),
|
||||
})
|
||||
}
|
||||
// branchBalances := make([]domain.BranchWalletBalance, 0, len(branches))
|
||||
// for _, b := range branches {
|
||||
// branchBalances = append(branchBalances, domain.BranchWalletBalance{
|
||||
// BranchID: b.ID,
|
||||
// BranchName: b.Name,
|
||||
// CompanyID: b.CompanyID,
|
||||
// Balance: float64(b.Balance.Float32()),
|
||||
// })
|
||||
// }
|
||||
|
||||
payload := domain.LiveWalletMetrics{
|
||||
Timestamp: time.Now(),
|
||||
CompanyBalances: companyBalances,
|
||||
BranchBalances: branchBalances,
|
||||
}
|
||||
// payload := domain.LiveWalletMetrics{
|
||||
// Timestamp: time.Now(),
|
||||
// CompanyBalances: companyBalances,
|
||||
// BranchBalances: branchBalances,
|
||||
// }
|
||||
|
||||
updatedData, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// updatedData, err := json.Marshal(payload)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
if err := s.redisClient.Set(ctx, key, updatedData, 0).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
// if err := s.redisClient.Set(ctx, key, updatedData, 0).Err(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
if err := s.redisClient.Publish(ctx, key, updatedData).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// if err := s.redisClient.Publish(ctx, key, updatedData).Err(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (s *Service) GetLiveMetrics(ctx context.Context) (domain.LiveMetric, error) {
|
||||
const key = "live_metrics"
|
||||
var metric domain.LiveMetric
|
||||
// func (s *Service) GetLiveMetrics(ctx context.Context) (domain.LiveMetric, error) {
|
||||
// const key = "live_metrics"
|
||||
// var metric domain.LiveMetric
|
||||
|
||||
val, err := s.redisClient.Get(ctx, key).Result()
|
||||
if err == redis.Nil {
|
||||
// Key does not exist yet, return zero-valued struct
|
||||
return domain.LiveMetric{}, nil
|
||||
} else if err != nil {
|
||||
return domain.LiveMetric{}, err
|
||||
}
|
||||
// val, err := s.redisClient.Get(ctx, key).Result()
|
||||
// if err == redis.Nil {
|
||||
// // Key does not exist yet, return zero-valued struct
|
||||
// return domain.LiveMetric{}, nil
|
||||
// } else if err != nil {
|
||||
// return domain.LiveMetric{}, err
|
||||
// }
|
||||
|
||||
if err := json.Unmarshal([]byte(val), &metric); err != nil {
|
||||
return domain.LiveMetric{}, err
|
||||
}
|
||||
// if err := json.Unmarshal([]byte(val), &metric); err != nil {
|
||||
// return domain.LiveMetric{}, err
|
||||
// }
|
||||
|
||||
return metric, nil
|
||||
}
|
||||
// return metric, nil
|
||||
// }
|
||||
// func (s *Service) StartKafkaConsumer(ctx context.Context) {
|
||||
// go func() {
|
||||
// for {
|
||||
// m, err := s.reader.ReadMessage(ctx)
|
||||
// if err != nil {
|
||||
// if err == context.Canceled {
|
||||
// s.mongoLogger.Info("[NotificationSvc.KafkaConsumer] Stopped by context")
|
||||
// return
|
||||
// }
|
||||
// s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Error reading message",
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// time.Sleep(1 * time.Second) // backoff
|
||||
// continue
|
||||
// }
|
||||
|
||||
func (s *Service) StartKafkaConsumer(ctx context.Context) {
|
||||
go func() {
|
||||
for {
|
||||
m, err := s.reader.ReadMessage(ctx)
|
||||
if err != nil {
|
||||
if err == context.Canceled {
|
||||
s.mongoLogger.Info("[NotificationSvc.KafkaConsumer] Stopped by context")
|
||||
return
|
||||
}
|
||||
s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Error reading message",
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
time.Sleep(1 * time.Second) // backoff
|
||||
continue
|
||||
}
|
||||
// var walletEvent event.WalletEvent
|
||||
// if err := json.Unmarshal(m.Value, &walletEvent); err != nil {
|
||||
// s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Failed to unmarshal wallet event",
|
||||
// zap.String("message", string(m.Value)),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// continue
|
||||
// }
|
||||
|
||||
var walletEvent event.WalletEvent
|
||||
if err := json.Unmarshal(m.Value, &walletEvent); err != nil {
|
||||
s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Failed to unmarshal wallet event",
|
||||
zap.String("message", string(m.Value)),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
continue
|
||||
}
|
||||
// raw, _ := json.Marshal(map[string]any{
|
||||
// "balance": walletEvent.Balance.Float32(),
|
||||
// "type": walletEvent.WalletType,
|
||||
// "timestamp": time.Now(),
|
||||
// })
|
||||
|
||||
raw, _ := json.Marshal(map[string]any{
|
||||
"balance": walletEvent.Balance.Float32(),
|
||||
"type": walletEvent.WalletType,
|
||||
"timestamp": time.Now(),
|
||||
})
|
||||
// headline := ""
|
||||
// message := ""
|
||||
// var receiver domain.NotificationRecieverSide
|
||||
// switch walletEvent.WalletType {
|
||||
|
||||
headline := ""
|
||||
message := ""
|
||||
var receiver domain.NotificationRecieverSide
|
||||
switch walletEvent.WalletType {
|
||||
// case domain.StaticWalletType:
|
||||
// headline = "Referral and Bonus Wallet Updated"
|
||||
// message = fmt.Sprintf("Your referral and bonus wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
// receiver = domain.NotificationRecieverSideCustomer
|
||||
// case domain.RegularWalletType:
|
||||
// headline = "Wallet Updated"
|
||||
// message = fmt.Sprintf("Your wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
// receiver = domain.NotificationRecieverSideCustomer
|
||||
// case domain.BranchWalletType:
|
||||
// headline = "Branch Wallet Updated"
|
||||
// message = fmt.Sprintf("branch wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
// receiver = domain.NotificationRecieverSideBranchManager
|
||||
// case domain.CompanyWalletType:
|
||||
// headline = "Company Wallet Updated"
|
||||
// message = fmt.Sprintf("company wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
// receiver = domain.NotificationRecieverSideAdmin
|
||||
// }
|
||||
// // Handle the wallet event: send notification
|
||||
// notification := &domain.Notification{
|
||||
// RecipientID: walletEvent.UserID,
|
||||
// DeliveryChannel: domain.DeliveryChannelInApp,
|
||||
// Reciever: receiver,
|
||||
// Type: domain.NotificationTypeWalletUpdated,
|
||||
// DeliveryStatus: domain.DeliveryStatusPending,
|
||||
// IsRead: false,
|
||||
// Level: domain.NotificationLevelInfo,
|
||||
// Priority: 2,
|
||||
// Metadata: raw,
|
||||
// Payload: domain.NotificationPayload{
|
||||
// Headline: headline,
|
||||
// Message: message,
|
||||
// },
|
||||
// }
|
||||
|
||||
case domain.StaticWalletType:
|
||||
headline = "Referral and Bonus Wallet Updated"
|
||||
message = fmt.Sprintf("Your referral and bonus wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideCustomer
|
||||
case domain.RegularWalletType:
|
||||
headline = "Wallet Updated"
|
||||
message = fmt.Sprintf("Your wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideCustomer
|
||||
case domain.BranchWalletType:
|
||||
headline = "Branch Wallet Updated"
|
||||
message = fmt.Sprintf("branch wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideBranchManager
|
||||
case domain.CompanyWalletType:
|
||||
headline = "Company Wallet Updated"
|
||||
message = fmt.Sprintf("company wallet balance is now %.2f", walletEvent.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideAdmin
|
||||
}
|
||||
// Handle the wallet event: send notification
|
||||
notification := &domain.Notification{
|
||||
RecipientID: walletEvent.UserID,
|
||||
DeliveryChannel: domain.DeliveryChannelInApp,
|
||||
Reciever: receiver,
|
||||
Type: domain.NotificationTypeWalletUpdated,
|
||||
DeliveryStatus: domain.DeliveryStatusPending,
|
||||
IsRead: false,
|
||||
Level: domain.NotificationLevelInfo,
|
||||
Priority: 2,
|
||||
Metadata: raw,
|
||||
Payload: domain.NotificationPayload{
|
||||
Headline: headline,
|
||||
Message: message,
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.SendNotification(ctx, notification); err != nil {
|
||||
s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Failed to send notification",
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
// if err := s.SendNotification(ctx, notification); err != nil {
|
||||
// s.mongoLogger.Error("[NotificationSvc.KafkaConsumer] Failed to send notification",
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
// }
|
||||
|
||||
// func (s *Service) UpdateLiveWalletMetricForWallet(ctx context.Context, wallet domain.Wallet) {
|
||||
// var (
|
||||
|
|
|
|||
|
|
@ -17,31 +17,17 @@ type Service interface {
|
|||
GetALLPrematchOdds(ctx context.Context) ([]domain.OddMarket, error)
|
||||
// GetRawOddsByMarketID(ctx context.Context, marketID string, upcomingID string) (domain.OddMarket, error)
|
||||
DeleteOddsForEvent(ctx context.Context, eventID string) error
|
||||
|
||||
GetOddByID(ctx context.Context, id int64) (domain.OddMarket, error)
|
||||
GetOddsWithSettingsByID(ctx context.Context, ID int64, companyID int64) (domain.OddMarketWithSettings, error)
|
||||
|
||||
// Settings
|
||||
SaveOddsSetting(ctx context.Context, odd domain.CreateOddMarketSettings) error
|
||||
UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error
|
||||
DeleteAllCompanyOddsSetting(ctx context.Context, companyID int64) error
|
||||
DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error
|
||||
|
||||
// Odd History
|
||||
InsertOddHistory(ctx context.Context, odd domain.CreateOddHistory) (domain.OddHistory, error)
|
||||
GetAllOddHistory(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error)
|
||||
GetInitialOddPerDay(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error)
|
||||
|
||||
// Disabling Odds
|
||||
InsertDisabledOdd(ctx context.Context, odd domain.CreateDisabledOdd) (domain.DisabledOdd, error)
|
||||
GetAllDisabledOdds(ctx context.Context) ([]domain.DisabledOdd, error)
|
||||
GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (domain.DisabledOdd, error)
|
||||
GetDisabledOddByID(ctx context.Context, id int64) (domain.DisabledOdd, error)
|
||||
DeleteDisabledOddsByID(ctx context.Context, id int64) error
|
||||
DeleteDisabledOddsByRawOddID(ctx context.Context, id int64) error
|
||||
|
||||
// Custom Odds
|
||||
// InsertCustomOdds(ctx context.Context, odd domain.CreateCustomOdd) (domain.CustomOdd, error)
|
||||
// GetAllCustomOdds(ctx context.Context, filter domain.CustomOddFilter) ([]domain.CustomOdd, error)
|
||||
// GetCustomOddByID(ctx context.Context, id int64) (domain.CustomOdd, error)
|
||||
// GetCustomOddByOddID(ctx context.Context, oddId int64, companyID int64) (domain.CustomOdd, error)
|
||||
// DeleteCustomOddByID(ctx context.Context, id int64) error
|
||||
// DeleteCustomOddsByOddID(ctx context.Context, oddId int64, companyID int64) error
|
||||
// DeleteCustomOddByEventID(ctx context.Context, eventID string) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -562,6 +562,7 @@ func (s *ServiceImpl) storeSection(ctx context.Context, eventID int64, fi, secti
|
|||
MarketType: marketType,
|
||||
MarketName: market.Name,
|
||||
MarketID: marketIDint,
|
||||
NumberOfOutcomes: int64(len(market.Odds)),
|
||||
UpdatedAt: updatedAt,
|
||||
Odds: marketOdds,
|
||||
// bwin won't reach this code so bet365 is hardcoded for now
|
||||
|
|
@ -676,6 +677,10 @@ func (s *ServiceImpl) SaveOddsSetting(ctx context.Context, odd domain.CreateOddM
|
|||
return s.store.SaveOddsSetting(ctx, odd)
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) UpdateGlobalOddsSetting(ctx context.Context, odd domain.UpdateGlobalOddMarketSettings) error {
|
||||
return s.store.UpdateGlobalOddsSetting(ctx, odd)
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) SaveOddsSettingReq(ctx context.Context, companyID int64, req domain.CreateOddMarketSettingsReq) error {
|
||||
|
||||
odd, err := s.GetOddsWithSettingsByID(ctx, req.OddMarketID, companyID)
|
||||
|
|
@ -741,6 +746,14 @@ func (s *ServiceImpl) DeleteOddsForEvent(ctx context.Context, eventID int64) err
|
|||
return s.store.DeleteOddsForEvent(ctx, eventID)
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) DeleteAllCompanyOddsSetting(ctx context.Context, companyID int64) error {
|
||||
return s.store.DeleteAllCompanyOddsSetting(ctx, companyID)
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) DeleteCompanyOddsSettingByOddMarketID(ctx context.Context, companyID int64, oddMarketID int64) error {
|
||||
return s.store.DeleteCompanyOddsSettingByOddMarketID(ctx, companyID, oddMarketID)
|
||||
}
|
||||
|
||||
// func getString(v interface{}) string {
|
||||
// if str, ok := v.(string); ok {
|
||||
// return str
|
||||
|
|
|
|||
|
|
@ -16,9 +16,12 @@ type RaffleStore interface {
|
|||
CreateRaffleWinner(ctx context.Context, raffleWinnerParams domain.RaffleWinnerParams) error
|
||||
SetRaffleComplete(ctx context.Context, raffleID int32) error
|
||||
CheckValidSportRaffleFilter(ctx context.Context, raffleID int32, sportID, leagueID int64) (bool, error)
|
||||
CheckSportRaffleHasFilter(ctx context.Context, raffleID int32) (bool, error)
|
||||
|
||||
CreateRaffleTicket(ctx context.Context, raffleTicketParams domain.CreateRaffleTicket) (domain.RaffleTicket, error)
|
||||
GetUserRaffleTickets(ctx context.Context, userID int32) ([]domain.RaffleTicketRes, error)
|
||||
SuspendRaffleTicket(ctx context.Context, raffleTicketID int32) error
|
||||
UnSuspendRaffleTicket(ctx context.Context, raffleID int32) error
|
||||
GetRaffleTicketCount(ctx context.Context, raffleID, userID int32) (int64, error)
|
||||
GetRaffleTicketLimit(ctx context.Context, raffleID int32) (int32, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,3 +64,15 @@ func (s *Service) UnSuspendRaffleTicket(ctx context.Context, raffleID int32) err
|
|||
func (s *Service) CheckValidSportRaffleFilter(ctx context.Context, raffleID int32, sportID, leagueID int64) (bool, error) {
|
||||
return s.raffleStore.CheckValidSportRaffleFilter(ctx, raffleID, sportID, leagueID)
|
||||
}
|
||||
|
||||
func (s *Service) CheckSportRaffleHasFilter(ctx context.Context, raffleID int32) (bool, error) {
|
||||
return s.raffleStore.CheckSportRaffleHasFilter(ctx, raffleID)
|
||||
}
|
||||
|
||||
func (s *Service) GetRaffleTicketCount(ctx context.Context, raffleID, userID int32) (int64, error) {
|
||||
return s.raffleStore.GetRaffleTicketCount(ctx, raffleID, userID)
|
||||
}
|
||||
|
||||
func (s *Service) GetRaffleTicketLimit(ctx context.Context, raffleID int32) (int32, error) {
|
||||
return s.raffleStore.GetRaffleTicketLimit(ctx, raffleID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,11 +135,11 @@ func (s *Service) GetDashboardSummary(ctx context.Context, filter domain.ReportF
|
|||
}
|
||||
|
||||
// Get sport/game metrics
|
||||
summary.TotalGames, summary.ActiveGames, summary.InactiveGames, err = s.virtulaGamesStore.GetGameCounts(ctx, filter)
|
||||
if err != nil {
|
||||
s.logger.Error("failed to get game counts", "error", err)
|
||||
return domain.DashboardSummary{}, err
|
||||
}
|
||||
// summary.TotalGames, summary.ActiveGames, summary.InactiveGames, err = s.virtulaGamesStore.GetGameCounts(ctx, filter)
|
||||
// if err != nil {
|
||||
// s.logger.Error("failed to get game counts", "error", err)
|
||||
// return domain.DashboardSummary{}, err
|
||||
// }
|
||||
|
||||
// Get company metrics
|
||||
summary.TotalCompanies, summary.ActiveCompanies, summary.InactiveCompanies, err = s.companyStore.GetCompanyCounts(ctx, filter)
|
||||
|
|
|
|||
292
internal/services/result/notification.go
Normal file
292
internal/services/result/notification.go
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
package result
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (s *Service) CheckAndSendResultNotifications(ctx context.Context, createdAfter time.Time) error {
|
||||
|
||||
resultLog, err := s.repo.GetAllResultLog(ctx, domain.ResultLogFilter{
|
||||
CreatedAfter: domain.ValidTime{
|
||||
Value: createdAfter,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.mongoLogger.Error(
|
||||
"Failed to get result log",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(resultLog) == 0 {
|
||||
s.mongoLogger.Info(
|
||||
"No results found for check and send result notification",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
totalResultLog := domain.ResultLog{
|
||||
StatusNotFinishedCount: resultLog[0].StatusNotFinishedCount,
|
||||
StatusPostponedCount: resultLog[0].StatusPostponedCount,
|
||||
}
|
||||
for _, log := range resultLog {
|
||||
// Add all the bets
|
||||
totalResultLog.StatusNotFinishedBets += log.StatusNotFinishedBets
|
||||
totalResultLog.StatusPostponedBets += log.StatusPostponedBets
|
||||
totalResultLog.StatusToBeFixedBets += log.StatusToBeFixedBets
|
||||
totalResultLog.StatusRemovedBets += log.StatusRemovedBets
|
||||
totalResultLog.StatusEndedBets += log.StatusEndedBets
|
||||
|
||||
totalResultLog.StatusToBeFixedCount += log.StatusToBeFixedCount
|
||||
totalResultLog.StatusRemovedCount += log.StatusRemovedCount
|
||||
totalResultLog.StatusEndedCount += log.StatusEndedCount
|
||||
totalResultLog.RemovedCount += log.RemovedCount
|
||||
}
|
||||
|
||||
err = s.SendAdminResultStatusErrorNotification(ctx, totalResultLog, createdAfter, time.Now())
|
||||
if err != nil {
|
||||
s.mongoLogger.Error(
|
||||
"Failed to send admin result status notification",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildHeadlineAndMessage(counts domain.ResultLog, createdAfter time.Time, endTime time.Time) (string, string) {
|
||||
period := fmt.Sprintf("%s - %s", createdAfter.Format("02 Jan 2006"), endTime.Format("02 Jan 2006"))
|
||||
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets + counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
if totalIssues == 0 {
|
||||
return "✅ Successfully Processed Event Results", fmt.Sprintf(
|
||||
"%d total ended events with %d total bets. No issues detected", counts.StatusEndedCount, totalBets,
|
||||
)
|
||||
}
|
||||
|
||||
parts := []string{}
|
||||
if counts.StatusNotFinishedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d unfinished with %d bets", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
}
|
||||
if counts.StatusToBeFixedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d to-fix with %d bets", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
}
|
||||
if counts.StatusPostponedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d postponed with %d bets", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
}
|
||||
if counts.StatusRemovedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d removed with %d bets", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
}
|
||||
if counts.StatusEndedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d ended with %d bets", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
}
|
||||
|
||||
headline := "⚠️ Issues Found Processing Event Results"
|
||||
message := fmt.Sprintf("Processed expired event results (%s): %s. Please review pending entries.",
|
||||
period, strings.Join(parts, ", "))
|
||||
return headline, message
|
||||
}
|
||||
|
||||
func buildHeadlineAndMessageEmail(counts domain.ResultLog, user domain.User, createdAfter time.Time, endTime time.Time) (string, string, string) {
|
||||
period := fmt.Sprintf("%s - %s", createdAfter.Format("02 Jan 2006"), endTime.Format("02 Jan 2006"))
|
||||
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount +
|
||||
counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalEvents := counts.StatusEndedCount + counts.StatusNotFinishedCount +
|
||||
counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets +
|
||||
counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
|
||||
greeting := fmt.Sprintf("Hi %s %s,", user.FirstName, user.LastName)
|
||||
|
||||
if totalIssues == 0 {
|
||||
headline := "✅ Weekly Results Report — All Events Processed Successfully"
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Weekly Results Summary (%s):
|
||||
- %d Ended Events
|
||||
- %d Total Bets
|
||||
|
||||
All events were processed successfully, and no issues were detected.
|
||||
|
||||
Best regards,
|
||||
The System`, greeting, period, counts.StatusEndedCount, totalBets)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Weekly Results Summary</h2>
|
||||
<p><em>Period: %s</em></p>
|
||||
<ul>
|
||||
<li><strong>%d Ended Events</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p>All events were processed successfully, and no issues were detected.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting, period, counts.StatusEndedCount, totalBets)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
partsPlain := []string{}
|
||||
partsHTML := []string{}
|
||||
|
||||
if counts.StatusNotFinishedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Incomplete Events (%d Bets)", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Incomplete Events</strong> (%d Bets)</li>", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
}
|
||||
if counts.StatusToBeFixedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Requires Review (%d Bets)", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Requires Review</strong> (%d Bets)</li>", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
}
|
||||
if counts.StatusPostponedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Postponed Events (%d Bets)", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Postponed Events</strong> (%d Bets)</li>", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
}
|
||||
if counts.StatusRemovedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Discarded Events (%d Bets)", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Discarded Events</strong> (%d Bets)</li>", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
}
|
||||
if counts.StatusEndedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Successfully Ended Events (%d Bets)", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Successfully Ended Events</strong> (%d Bets)</li>", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
}
|
||||
|
||||
headline := "⚠️ Weekly Results Report — Review Required"
|
||||
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Weekly Results Summary (%s):
|
||||
%s
|
||||
|
||||
Totals:
|
||||
- %d Events Processed
|
||||
- %d Total Bets
|
||||
|
||||
Next Steps:
|
||||
Some events require your attention. Please log into the admin dashboard to review pending issues.
|
||||
|
||||
Best regards,
|
||||
The System`,
|
||||
greeting,
|
||||
period,
|
||||
strings.Join(partsPlain, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Weekly Results Summary</h2>
|
||||
<p><em>Period: %s</em></p>
|
||||
<ul>
|
||||
%s
|
||||
</ul>
|
||||
<h3>Totals</h3>
|
||||
<ul>
|
||||
<li><strong>%d Events Processed</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p><strong>Next Steps:</strong><br>Some events require your attention. Please <a href="https://admin.fortunebets.net">log into the admin dashboard</a> to review pending issues.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting,
|
||||
period,
|
||||
strings.Join(partsHTML, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
func (s *Service) SendAdminResultStatusErrorNotification(
|
||||
ctx context.Context,
|
||||
counts domain.ResultLog,
|
||||
createdAfter time.Time,
|
||||
endTime time.Time,
|
||||
) error {
|
||||
|
||||
superAdmins, _, err := s.userSvc.GetAllUsers(ctx, domain.UserFilter{
|
||||
Role: string(domain.RoleSuperAdmin),
|
||||
})
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get super_admin recipients", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
metaBytes, err := json.Marshal(counts)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to marshal metadata", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
headline, message := buildHeadlineAndMessage(counts, createdAfter, endTime)
|
||||
|
||||
notification := &domain.Notification{
|
||||
ErrorSeverity: domain.NotificationErrorSeverityHigh,
|
||||
DeliveryStatus: domain.DeliveryStatusPending,
|
||||
IsRead: false,
|
||||
Type: domain.NOTIFICATION_TYPE_BET_RESULT,
|
||||
Level: domain.NotificationLevelWarning,
|
||||
Reciever: domain.NotificationRecieverSideAdmin,
|
||||
DeliveryChannel: domain.DeliveryChannelInApp,
|
||||
Payload: domain.NotificationPayload{
|
||||
Headline: headline,
|
||||
Message: message,
|
||||
},
|
||||
Priority: 2,
|
||||
Metadata: metaBytes,
|
||||
}
|
||||
|
||||
var sendErrors []error
|
||||
for _, user := range superAdmins {
|
||||
notification.RecipientID = user.ID
|
||||
if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin notification",
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendErrors = append(sendErrors, err)
|
||||
}
|
||||
// notification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
if user.Email == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
subject, plain, html := buildHeadlineAndMessageEmail(counts, user, createdAfter, endTime)
|
||||
if err := s.messengerSvc.SendEmail(ctx, user.Email, plain, html, subject); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin result report email",
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendErrors = append(sendErrors, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(sendErrors) > 0 {
|
||||
return fmt.Errorf("sent with partial failure: %d errors", len(sendErrors))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -262,7 +262,6 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
|
|||
eventLogger := s.mongoLogger.With(
|
||||
zap.Int64("eventID", event.ID),
|
||||
)
|
||||
|
||||
result, err := s.FetchB365Result(ctx, event.SourceEventID)
|
||||
if err != nil {
|
||||
if err == ErrEventIsNotActive {
|
||||
|
|
@ -457,276 +456,6 @@ func (s *Service) FetchB365ResultAndUpdateBets(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) CheckAndSendResultNotifications(ctx context.Context, createdAfter time.Time) error {
|
||||
|
||||
resultLog, err := s.repo.GetAllResultLog(ctx, domain.ResultLogFilter{
|
||||
CreatedAfter: domain.ValidTime{
|
||||
Value: createdAfter,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
s.mongoLogger.Error(
|
||||
"Failed to get result log",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(resultLog) == 0 {
|
||||
s.mongoLogger.Info(
|
||||
"No results found for check and send result notification",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
totalResultLog := domain.ResultLog{
|
||||
StatusNotFinishedCount: resultLog[0].StatusNotFinishedCount,
|
||||
StatusPostponedCount: resultLog[0].StatusPostponedCount,
|
||||
}
|
||||
for _, log := range resultLog {
|
||||
// Add all the bets
|
||||
totalResultLog.StatusNotFinishedBets += log.StatusNotFinishedBets
|
||||
totalResultLog.StatusPostponedBets += log.StatusPostponedBets
|
||||
totalResultLog.StatusToBeFixedBets += log.StatusToBeFixedBets
|
||||
totalResultLog.StatusRemovedBets += log.StatusRemovedBets
|
||||
totalResultLog.StatusEndedBets += log.StatusEndedBets
|
||||
|
||||
totalResultLog.StatusToBeFixedCount += log.StatusToBeFixedCount
|
||||
totalResultLog.StatusRemovedCount += log.StatusRemovedCount
|
||||
totalResultLog.StatusEndedCount += log.StatusEndedCount
|
||||
totalResultLog.RemovedCount += log.RemovedCount
|
||||
}
|
||||
|
||||
err = s.SendAdminResultStatusErrorNotification(ctx, totalResultLog)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error(
|
||||
"Failed to send admin result status notification",
|
||||
zap.Time("CreatedAfter", createdAfter),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildHeadlineAndMessage(counts domain.ResultLog) (string, string) {
|
||||
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets + counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
if totalIssues == 0 {
|
||||
return "✅ Successfully Processed Event Results", fmt.Sprintf(
|
||||
"%d total ended events with %d total bets. No issues detected", counts.StatusEndedCount, totalBets,
|
||||
)
|
||||
}
|
||||
|
||||
parts := []string{}
|
||||
if counts.StatusNotFinishedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d unfinished with %d bets", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
}
|
||||
if counts.StatusToBeFixedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d to-fix with %d bets", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
}
|
||||
if counts.StatusPostponedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d postponed with %d bets", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
}
|
||||
if counts.StatusRemovedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d removed with %d bets", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
}
|
||||
if counts.StatusEndedCount > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d ended with %d bets", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
}
|
||||
|
||||
headline := "⚠️ Issues Found Processing Event Results"
|
||||
message := fmt.Sprintf("Processed expired event results: %s. Please review pending entries.", strings.Join(parts, ", "))
|
||||
return headline, message
|
||||
}
|
||||
|
||||
func buildHeadlineAndMessageEmail(counts domain.ResultLog, user domain.User) (string, string, string) {
|
||||
totalIssues := counts.StatusNotFinishedCount + counts.StatusToBeFixedCount +
|
||||
counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalEvents := counts.StatusEndedCount + counts.StatusNotFinishedCount +
|
||||
counts.StatusToBeFixedCount + counts.StatusPostponedCount + counts.StatusRemovedCount
|
||||
totalBets := counts.StatusEndedBets + counts.StatusNotFinishedBets +
|
||||
counts.StatusPostponedBets + counts.StatusRemovedBets + counts.StatusToBeFixedBets
|
||||
|
||||
greeting := fmt.Sprintf("Hi %s %s,", user.FirstName, user.LastName)
|
||||
|
||||
if totalIssues == 0 {
|
||||
headline := "✅ Weekly Results Report — All Events Processed Successfully"
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Weekly Results Summary:
|
||||
- %d Ended Events
|
||||
- %d Total Bets
|
||||
|
||||
All events were processed successfully, and no issues were detected.
|
||||
|
||||
Best regards,
|
||||
The System`, greeting, counts.StatusEndedCount, totalBets)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Weekly Results Summary</h2>
|
||||
<ul>
|
||||
<li><strong>%d Ended Events</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p>All events were processed successfully, and no issues were detected.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting, counts.StatusEndedCount, totalBets)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
partsPlain := []string{}
|
||||
partsHTML := []string{}
|
||||
|
||||
if counts.StatusNotFinishedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Incomplete Events (%d Bets)", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Incomplete Events</strong> (%d Bets)</li>", counts.StatusNotFinishedCount, counts.StatusNotFinishedBets))
|
||||
}
|
||||
if counts.StatusToBeFixedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Requires Review (%d Bets)", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Requires Review</strong> (%d Bets)</li>", counts.StatusToBeFixedCount, counts.StatusToBeFixedBets))
|
||||
}
|
||||
if counts.StatusPostponedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Postponed Events (%d Bets)", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Postponed Events</strong> (%d Bets)</li>", counts.StatusPostponedCount, counts.StatusPostponedBets))
|
||||
}
|
||||
if counts.StatusRemovedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Discarded Events (%d Bets)", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Discarded Events</strong> (%d Bets)</li>", counts.StatusRemovedCount, counts.StatusRemovedBets))
|
||||
}
|
||||
if counts.StatusEndedCount > 0 {
|
||||
partsPlain = append(partsPlain,
|
||||
fmt.Sprintf("- %d Successfully Ended Events (%d Bets)", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
partsHTML = append(partsHTML,
|
||||
fmt.Sprintf("<li><strong>%d Successfully Ended Events</strong> (%d Bets)</li>", counts.StatusEndedCount, counts.StatusEndedBets))
|
||||
}
|
||||
|
||||
headline := "⚠️ Weekly Results Report — Review Required"
|
||||
|
||||
plain := fmt.Sprintf(`%s
|
||||
|
||||
Weekly Results Summary:
|
||||
%s
|
||||
|
||||
Totals:
|
||||
- %d Events Processed
|
||||
- %d Total Bets
|
||||
|
||||
Next Steps:
|
||||
Some events require your attention. Please log into the admin dashboard to review pending issues.
|
||||
|
||||
Best regards,
|
||||
The System`,
|
||||
greeting,
|
||||
strings.Join(partsPlain, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
html := fmt.Sprintf(`<p>%s</p>
|
||||
<h2>Weekly Results Summary</h2>
|
||||
<ul>
|
||||
%s
|
||||
</ul>
|
||||
<h3>Totals</h3>
|
||||
<ul>
|
||||
<li><strong>%d Events Processed</strong></li>
|
||||
<li><strong>%d Total Bets</strong></li>
|
||||
</ul>
|
||||
<p><strong>Next Steps:</strong><br>Some events require your attention. Please <a href="https://admin.fortunebets.net">log into the admin dashboard</a> to review pending issues.</p>
|
||||
<p>Best regards,<br>The System</p>`,
|
||||
greeting,
|
||||
strings.Join(partsHTML, "\n"),
|
||||
totalEvents,
|
||||
totalBets,
|
||||
)
|
||||
|
||||
return headline, plain, html
|
||||
}
|
||||
|
||||
func (s *Service) SendAdminResultStatusErrorNotification(
|
||||
ctx context.Context,
|
||||
counts domain.ResultLog,
|
||||
) error {
|
||||
|
||||
superAdmins, _, err := s.userSvc.GetAllUsers(ctx, domain.UserFilter{
|
||||
Role: string(domain.RoleSuperAdmin),
|
||||
})
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get super_admin recipients", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
metaBytes, err := json.Marshal(counts)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to marshal metadata", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
headline, message := buildHeadlineAndMessage(counts)
|
||||
|
||||
notification := &domain.Notification{
|
||||
ErrorSeverity: domain.NotificationErrorSeverityHigh,
|
||||
DeliveryStatus: domain.DeliveryStatusPending,
|
||||
IsRead: false,
|
||||
Type: domain.NOTIFICATION_TYPE_BET_RESULT,
|
||||
Level: domain.NotificationLevelWarning,
|
||||
Reciever: domain.NotificationRecieverSideAdmin,
|
||||
DeliveryChannel: domain.DeliveryChannelInApp,
|
||||
Payload: domain.NotificationPayload{
|
||||
Headline: headline,
|
||||
Message: message,
|
||||
},
|
||||
Priority: 2,
|
||||
Metadata: metaBytes,
|
||||
}
|
||||
|
||||
var sendErrors []error
|
||||
for _, user := range superAdmins {
|
||||
notification.RecipientID = user.ID
|
||||
if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin notification",
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendErrors = append(sendErrors, err)
|
||||
}
|
||||
// notification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
if user.Email == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
subject, plain, html := buildHeadlineAndMessageEmail(counts, user)
|
||||
if err := s.messengerSvc.SendEmail(ctx, user.Email, plain, html, subject); err != nil {
|
||||
s.mongoLogger.Error("failed to send admin result report email",
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendErrors = append(sendErrors, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(sendErrors) > 0 {
|
||||
return fmt.Errorf("sent with partial failure: %d errors", len(sendErrors))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) CheckAndUpdateExpiredB365Events(ctx context.Context) (int64, error) {
|
||||
events, _, err := s.repo.GetAllEvents(ctx, domain.EventFilter{
|
||||
LastStartTime: domain.ValidTime{
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ func (s *Service) CreateShopDeposit(ctx context.Context, userID int64, role doma
|
|||
// }
|
||||
|
||||
newTransaction, err := s.CreateShopTransaction(ctx, domain.CreateShopTransaction{
|
||||
Amount: domain.Currency(req.Amount),
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
BranchID: branchID,
|
||||
CompanyID: companyID,
|
||||
UserID: userID,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ type VirtualGameService interface {
|
|||
ProcessTournamentWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error)
|
||||
ProcessPromoWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error)
|
||||
|
||||
GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
// GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
ListGames(ctx context.Context, currency string) ([]domain.PopOKGame, error)
|
||||
RecommendGames(ctx context.Context, userID int64) ([]domain.GameRecommendation, error)
|
||||
AddFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
|
|
|
|||
|
|
@ -657,9 +657,9 @@ func (s *service) verifySignature(callback *domain.PopOKCallback) bool {
|
|||
return expected == callback.Signature
|
||||
}
|
||||
|
||||
func (s *service) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
|
||||
return s.repo.GetGameCounts(ctx, filter)
|
||||
}
|
||||
// func (s *service) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
|
||||
// return s.repo.GetGameCounts(ctx, filter)
|
||||
// }
|
||||
|
||||
func (s *service) ListGames(ctx context.Context, currency string) ([]domain.PopOKGame, error) {
|
||||
now := time.Now().Format("02-01-2006 15:04:05") // dd-mm-yyyy hh:mm:ss
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
)
|
||||
|
||||
// InitiateDirectDeposit creates a pending deposit request
|
||||
|
|
@ -73,8 +72,8 @@ func (s *Service) VerifyDirectDeposit(
|
|||
}
|
||||
|
||||
// Publish wallet update event
|
||||
go s.publishWalletUpdate(ctx, deposit.WalletID, deposit.Wallet.UserID,
|
||||
deposit.Wallet.Balance+deposit.Amount, "direct_deposit_verified")
|
||||
// go s.publishWalletUpdate(ctx, deposit.WalletID, deposit.Wallet.UserID,
|
||||
// deposit.Wallet.Balance+deposit.Amount, "direct_deposit_verified")
|
||||
|
||||
// Update deposit status
|
||||
deposit.Status = domain.DepositStatusCompleted
|
||||
|
|
@ -206,12 +205,12 @@ func (s *Service) notifyCustomerVerificationResult(ctx context.Context, deposit
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Service) publishWalletUpdate(ctx context.Context, walletID, userID int64, newBalance domain.Currency, trigger string) {
|
||||
s.kafkaProducer.Publish(ctx, fmt.Sprint(walletID), event.WalletEvent{
|
||||
EventType: event.WalletBalanceUpdated,
|
||||
WalletID: walletID,
|
||||
UserID: userID,
|
||||
Balance: newBalance,
|
||||
Trigger: trigger,
|
||||
})
|
||||
}
|
||||
// func (s *Service) publishWalletUpdate(ctx context.Context, walletID, userID int64, newBalance domain.Currency, trigger string) {
|
||||
// s.kafkaProducer.Publish(ctx, fmt.Sprint(walletID), event.WalletEvent{
|
||||
// EventType: event.WalletBalanceUpdated,
|
||||
// WalletID: walletID,
|
||||
// UserID: userID,
|
||||
// Balance: newBalance,
|
||||
// Trigger: trigger,
|
||||
// })
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ package wallet
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s *Service) GetAdminNotificationRecipients(ctx context.Context, walletID int64, walletType domain.WalletType) ([]int64, error) {
|
||||
|
|
@ -63,8 +65,61 @@ func (s *Service) GetAdminNotificationRecipients(ctx context.Context, walletID i
|
|||
return recipients, nil
|
||||
}
|
||||
|
||||
func (s *Service) SendWalletUpdateNotification(ctx context.Context, wallet domain.Wallet) error {
|
||||
raw, _ := json.Marshal(map[string]any{
|
||||
"balance": wallet.Balance.Float32(),
|
||||
"type": wallet.Type,
|
||||
"timestamp": time.Now(),
|
||||
})
|
||||
|
||||
headline := ""
|
||||
message := ""
|
||||
var receiver domain.NotificationRecieverSide
|
||||
switch wallet.Type {
|
||||
case domain.StaticWalletType:
|
||||
headline = "Referral and Bonus Wallet Updated"
|
||||
message = fmt.Sprintf("Your referral and bonus wallet balance is now %.2f", wallet.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideCustomer
|
||||
case domain.RegularWalletType:
|
||||
headline = "Wallet Updated"
|
||||
message = fmt.Sprintf("Your wallet balance is now %.2f", wallet.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideCustomer
|
||||
case domain.BranchWalletType:
|
||||
headline = "Branch Wallet Updated"
|
||||
message = fmt.Sprintf("branch wallet balance is now %.2f", wallet.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideBranchManager
|
||||
case domain.CompanyWalletType:
|
||||
headline = "Company Wallet Updated"
|
||||
message = fmt.Sprintf("company wallet balance is now %.2f", wallet.Balance.Float32())
|
||||
receiver = domain.NotificationRecieverSideAdmin
|
||||
}
|
||||
// Handle the wallet event: send notification
|
||||
notification := &domain.Notification{
|
||||
RecipientID: wallet.UserID,
|
||||
DeliveryChannel: domain.DeliveryChannelInApp,
|
||||
Reciever: receiver,
|
||||
Type: domain.NotificationTypeWalletUpdated,
|
||||
DeliveryStatus: domain.DeliveryStatusPending,
|
||||
IsRead: false,
|
||||
Level: domain.NotificationLevelInfo,
|
||||
Priority: 2,
|
||||
Metadata: raw,
|
||||
Payload: domain.NotificationPayload{
|
||||
Headline: headline,
|
||||
Message: message,
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
|
||||
s.mongoLogger.Error("[WalletSvc.SendWalletUpdateNotification] Failed to send notification",
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWallet domain.Wallet) error {
|
||||
// Send different messages
|
||||
|
|
@ -115,16 +170,16 @@ func (s *Service) SendAdminWalletLowNotification(ctx context.Context, adminWalle
|
|||
)
|
||||
}
|
||||
|
||||
adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
// adminNotification.DeliveryChannel = domain.DeliveryChannelEmail
|
||||
|
||||
if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
||||
s.mongoLogger.Error("failed to send email admin notification",
|
||||
zap.Int64("admin_id", adminID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// if err := s.notificationSvc.SendNotification(ctx, adminNotification); err != nil {
|
||||
// s.mongoLogger.Error("failed to send email admin notification",
|
||||
// zap.Int64("admin_id", adminID),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return err
|
||||
// }
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package wallet
|
|||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/kafka"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/kafka"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
"go.uber.org/zap"
|
||||
|
|
@ -18,7 +18,6 @@ type Service struct {
|
|||
userSvc *user.Service
|
||||
mongoLogger *zap.Logger
|
||||
logger *slog.Logger
|
||||
kafkaProducer *kafka.Producer
|
||||
}
|
||||
|
||||
func NewService(
|
||||
|
|
@ -29,7 +28,6 @@ func NewService(
|
|||
userSvc *user.Service,
|
||||
mongoLogger *zap.Logger,
|
||||
logger *slog.Logger,
|
||||
kafkaProducer *kafka.Producer,
|
||||
) *Service {
|
||||
return &Service{
|
||||
walletStore: walletStore,
|
||||
|
|
@ -40,6 +38,5 @@ func NewService(
|
|||
userSvc: userSvc,
|
||||
mongoLogger: mongoLogger,
|
||||
logger: logger,
|
||||
kafkaProducer: kafkaProducer,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,9 +52,11 @@ func (s *Service) TransferToWallet(ctx context.Context, senderID int64, receiver
|
|||
|
||||
senderWallet, err := s.GetWalletByID(ctx, senderID)
|
||||
if err != nil {
|
||||
|
||||
return domain.Transfer{}, err
|
||||
}
|
||||
if !senderWallet.IsActive {
|
||||
return domain.Transfer{}, ErrWalletIsDisabled
|
||||
}
|
||||
|
||||
if !senderWallet.IsTransferable {
|
||||
fmt.Printf("Error: %d Sender Wallet is not transferable \n", senderWallet.ID)
|
||||
|
|
@ -65,7 +67,9 @@ func (s *Service) TransferToWallet(ctx context.Context, senderID int64, receiver
|
|||
if err != nil {
|
||||
return domain.Transfer{}, err
|
||||
}
|
||||
|
||||
if !receiverWallet.IsActive {
|
||||
return domain.Transfer{}, ErrWalletIsDisabled
|
||||
}
|
||||
if !receiverWallet.IsTransferable {
|
||||
fmt.Printf("Error: %d Receiver Wallet is not transferable \n", senderWallet.ID)
|
||||
return domain.Transfer{}, ErrReceiverWalletNotTransferable
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ package wallet
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
// "fmt"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
"go.uber.org/zap"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/event"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrBalanceInsufficient = errors.New("wallet balance is insufficient")
|
||||
ErrWalletIsDisabled = errors.New("wallet is disabled")
|
||||
)
|
||||
|
||||
func (s *Service) CreateWallet(ctx context.Context, wallet domain.CreateWallet) (domain.Wallet, error) {
|
||||
|
|
@ -82,26 +85,37 @@ func (s *Service) GetAllBranchWallets(ctx context.Context) ([]domain.BranchWalle
|
|||
}
|
||||
|
||||
func (s *Service) UpdateBalance(ctx context.Context, id int64, balance domain.Currency) error {
|
||||
err := s.walletStore.UpdateBalance(ctx, id, balance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wallet, err := s.GetWalletByID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.UserID), event.WalletEvent{
|
||||
EventType: event.WalletBalanceUpdated,
|
||||
WalletID: wallet.ID,
|
||||
UserID: wallet.UserID,
|
||||
Balance: balance,
|
||||
WalletType: wallet.Type,
|
||||
Trigger: "UpdateBalance",
|
||||
})
|
||||
}()
|
||||
if !wallet.IsActive {
|
||||
return ErrWalletIsDisabled
|
||||
}
|
||||
|
||||
err = s.walletStore.UpdateBalance(ctx, id, balance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// go func() {
|
||||
// s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.UserID), event.WalletEvent{
|
||||
// EventType: event.WalletBalanceUpdated,
|
||||
// WalletID: wallet.ID,
|
||||
// UserID: wallet.UserID,
|
||||
// Balance: balance,
|
||||
// WalletType: wallet.Type,
|
||||
// Trigger: "UpdateBalance",
|
||||
// })
|
||||
// }()
|
||||
|
||||
if err := s.SendWalletUpdateNotification(ctx, wallet); err != nil {
|
||||
s.mongoLogger.Info("Failed to send wallet update notification",
|
||||
zap.Int64("wallet_id", wallet.ID),
|
||||
zap.Error(err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -112,22 +126,29 @@ func (s *Service) AddToWallet(
|
|||
if err != nil {
|
||||
return domain.Transfer{}, err
|
||||
}
|
||||
|
||||
if !wallet.IsActive {
|
||||
return domain.Transfer{}, ErrWalletIsDisabled
|
||||
}
|
||||
err = s.walletStore.UpdateBalance(ctx, id, wallet.Balance+amount)
|
||||
if err != nil {
|
||||
return domain.Transfer{}, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.ID), event.WalletEvent{
|
||||
EventType: event.WalletBalanceUpdated,
|
||||
WalletID: wallet.ID,
|
||||
UserID: wallet.UserID,
|
||||
Balance: wallet.Balance + amount,
|
||||
WalletType: wallet.Type,
|
||||
Trigger: "AddToWallet",
|
||||
})
|
||||
}()
|
||||
// go func() {
|
||||
// s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.ID), event.WalletEvent{
|
||||
// EventType: event.WalletBalanceUpdated,
|
||||
// WalletID: wallet.ID,
|
||||
// UserID: wallet.UserID,
|
||||
// Balance: wallet.Balance + amount,
|
||||
// WalletType: wallet.Type,
|
||||
// Trigger: "AddToWallet",
|
||||
// })
|
||||
// }()
|
||||
if err := s.SendWalletUpdateNotification(ctx, wallet); err != nil {
|
||||
s.mongoLogger.Info("Failed to send wallet update notification",
|
||||
zap.Int64("wallet_id", wallet.ID),
|
||||
zap.Error(err))
|
||||
}
|
||||
|
||||
// Log the transfer here for reference
|
||||
newTransfer, err := s.transferStore.CreateTransfer(ctx, domain.CreateTransfer{
|
||||
|
|
@ -153,6 +174,9 @@ func (s *Service) DeductFromWallet(ctx context.Context, id int64, amount domain.
|
|||
return domain.Transfer{}, err
|
||||
}
|
||||
|
||||
if !wallet.IsActive {
|
||||
return domain.Transfer{}, ErrWalletIsDisabled
|
||||
}
|
||||
if wallet.Balance < amount {
|
||||
// Send Wallet low to admin
|
||||
if wallet.Type == domain.CompanyWalletType || wallet.Type == domain.BranchWalletType {
|
||||
|
|
@ -173,8 +197,11 @@ func (s *Service) DeductFromWallet(ctx context.Context, id int64, amount domain.
|
|||
}
|
||||
|
||||
balance := wallet.Balance.Float32()
|
||||
if balance < thresholds[0] {
|
||||
for _, thresholds := range thresholds {
|
||||
if thresholds < balance && thresholds > (balance-amount.Float32()) {
|
||||
s.SendAdminWalletLowNotification(ctx, wallet)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,16 +211,22 @@ func (s *Service) DeductFromWallet(ctx context.Context, id int64, amount domain.
|
|||
return domain.Transfer{}, nil
|
||||
}
|
||||
|
||||
go func() {
|
||||
s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.ID), event.WalletEvent{
|
||||
EventType: event.WalletBalanceUpdated,
|
||||
WalletID: wallet.ID,
|
||||
UserID: wallet.UserID,
|
||||
Balance: wallet.Balance - amount,
|
||||
WalletType: wallet.Type,
|
||||
Trigger: "DeductFromWallet",
|
||||
})
|
||||
}()
|
||||
// go func() {
|
||||
// s.kafkaProducer.Publish(ctx, fmt.Sprint(wallet.ID), event.WalletEvent{
|
||||
// EventType: event.WalletBalanceUpdated,
|
||||
// WalletID: wallet.ID,
|
||||
// UserID: wallet.UserID,
|
||||
// Balance: wallet.Balance - amount,
|
||||
// WalletType: wallet.Type,
|
||||
// Trigger: "DeductFromWallet",
|
||||
// })
|
||||
// }()
|
||||
|
||||
if err := s.SendWalletUpdateNotification(ctx, wallet); err != nil {
|
||||
s.mongoLogger.Info("Failed to send wallet update notification",
|
||||
zap.Int64("wallet_id", wallet.ID),
|
||||
zap.Error(err))
|
||||
}
|
||||
|
||||
// Log the transfer here for reference
|
||||
newTransfer, err := s.transferStore.CreateTransfer(ctx, domain.CreateTransfer{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
betSvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
enetpulse "github.com/SamuelTariku/FortuneBet-Backend/internal/services/enet_pulse"
|
||||
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notification"
|
||||
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||
resultsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
|
|
@ -108,7 +109,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
mongoLogger.Info("Cron jobs started for event and odds services")
|
||||
}
|
||||
|
||||
func StartTicketCrons(ticketService ticket.Service, mongoLogger *zap.Logger) {
|
||||
func StartCleanupCrons(ticketService ticket.Service, notificationSvc *notificationservice.Service, mongoLogger *zap.Logger) {
|
||||
c := cron.New(cron.WithSeconds())
|
||||
|
||||
schedule := []struct {
|
||||
|
|
@ -128,6 +129,19 @@ func StartTicketCrons(ticketService ticket.Service, mongoLogger *zap.Logger) {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
spec: "0 0 0 * * 1", // Every Monday (Weekly)
|
||||
task: func() {
|
||||
mongoLogger.Info("Deleting old notifications")
|
||||
if err := notificationSvc.DeleteOldNotifications(context.Background()); err != nil {
|
||||
mongoLogger.Error("Failed to remove old notifications",
|
||||
zap.Error(err),
|
||||
)
|
||||
} else {
|
||||
mongoLogger.Info("Successfully deleted old notifications")
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, job := range schedule {
|
||||
|
|
@ -261,7 +275,7 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreSports(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store sports", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing sports")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing sports\n\n")
|
||||
}
|
||||
|
||||
// 2️⃣ Tournament Templates
|
||||
|
|
@ -269,7 +283,7 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreTournamentTemplates(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store tournament templates", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing tournament templates")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing tournament templates\n\n")
|
||||
}
|
||||
|
||||
// 3️⃣ Tournaments
|
||||
|
|
@ -277,7 +291,7 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreTournaments(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store tournaments", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing tournaments")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing tournaments\n\n")
|
||||
}
|
||||
|
||||
// 4️⃣ Tournament Stages
|
||||
|
|
@ -285,16 +299,16 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreTournamentStages(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store tournament stages", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing tournament stages")
|
||||
mongoLogger.Info("✅ \n\nCompleted fetching and storing tournament stages\n\n")
|
||||
}
|
||||
|
||||
// 5️⃣ Fixtures
|
||||
// // 5️⃣ Fixtures
|
||||
mongoLogger.Info("Began fetching and storing fixtures cron task")
|
||||
today := time.Now().Format("2006-01-02")
|
||||
if err := enetPulseSvc.FetchAndStoreFixtures(ctx, today); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store fixtures", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing fixtures")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing fixtures\n\n")
|
||||
}
|
||||
|
||||
// 6️⃣ Results
|
||||
|
|
@ -302,7 +316,7 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreResults(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store results", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing results")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing results\n\n")
|
||||
}
|
||||
|
||||
// 7 Outcome Types
|
||||
|
|
@ -310,15 +324,15 @@ func StartEnetPulseCron(enetPulseSvc *enetpulse.Service, mongoLogger *zap.Logger
|
|||
if err := enetPulseSvc.FetchAndStoreOutcomeTypes(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store outcome_types", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing outcome_types")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing outcome_types\n\n")
|
||||
}
|
||||
|
||||
// 8 Outcome Types
|
||||
// 8 Preodds
|
||||
mongoLogger.Info("Began fetching and storing preodds cron task")
|
||||
if err := enetPulseSvc.FetchAndStorePreodds(ctx); err != nil {
|
||||
mongoLogger.Error("Failed to fetch and store preodds", zap.Error(err))
|
||||
} else {
|
||||
mongoLogger.Info("✅ Completed fetching and storing preodds")
|
||||
mongoLogger.Info("\n\n✅ Completed fetching and storing preodds\n\n")
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -103,25 +103,25 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create admin:"+err.Error())
|
||||
}
|
||||
|
||||
if req.CompanyID != nil {
|
||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
ID: *req.CompanyID,
|
||||
AdminID: domain.ValidInt64{
|
||||
Value: newUser.ID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to update company with new admin",
|
||||
zap.Int64("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("company_id", *req.CompanyID),
|
||||
zap.Int64("admin_id", newUser.ID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company"+err.Error())
|
||||
}
|
||||
}
|
||||
// if req.CompanyID != nil {
|
||||
// _, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
// ID: *req.CompanyID,
|
||||
// AdminID: domain.ValidInt64{
|
||||
// Value: newUser.ID,
|
||||
// Valid: true,
|
||||
// },
|
||||
// })
|
||||
// if err != nil {
|
||||
// h.mongoLoggerSvc.Error("failed to update company with new admin",
|
||||
// zap.Int64("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Int64("company_id", *req.CompanyID),
|
||||
// zap.Int64("admin_id", newUser.ID),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company"+err.Error())
|
||||
// }
|
||||
// }
|
||||
|
||||
h.mongoLoggerSvc.Info("admin created successfully",
|
||||
zap.Int64("admin_id", newUser.ID),
|
||||
|
|
@ -283,7 +283,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value, int(total))
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value+1, int(total))
|
||||
}
|
||||
|
||||
// GetAdminByID godoc
|
||||
|
|
@ -451,24 +451,24 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update admin:"+err.Error())
|
||||
}
|
||||
|
||||
if req.CompanyID != nil {
|
||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
ID: *req.CompanyID,
|
||||
AdminID: domain.ValidInt64{
|
||||
Value: AdminID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed to update company",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("admin_id", AdminID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company:"+err.Error())
|
||||
}
|
||||
}
|
||||
// if req.CompanyID != nil {
|
||||
// _, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
// ID: *req.CompanyID,
|
||||
// AdminID: domain.ValidInt64{
|
||||
// Value: AdminID,
|
||||
// Valid: true,
|
||||
// },
|
||||
// })
|
||||
// if err != nil {
|
||||
// h.mongoLoggerSvc.Error("UpdateAdmin failed to update company",
|
||||
// zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Int64("admin_id", AdminID),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company:"+err.Error())
|
||||
// }
|
||||
// }
|
||||
|
||||
h.mongoLoggerSvc.Info("UpdateAdmin succeeded",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
|
|
|
|||
|
|
@ -259,23 +259,52 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
|||
sportAndLeagueIDs = append(sportAndLeagueIDs, ids)
|
||||
}
|
||||
|
||||
fmt.Println("sportAndLeagueIDs: ", sportAndLeagueIDs)
|
||||
|
||||
for _, raffle := range raffles {
|
||||
// TODO: only fetch pending raffles from db
|
||||
if raffle.Status == "completed" {
|
||||
continue
|
||||
}
|
||||
|
||||
// only require one sport and league combo to be valide to make the raffle ticket
|
||||
foundValid := false
|
||||
for _, sportAndLeagueID := range sportAndLeagueIDs {
|
||||
res, err := h.raffleSvc.CheckValidSportRaffleFilter(c.Context(), raffle.ID, sportAndLeagueID[0], sportAndLeagueID[1])
|
||||
raffleTicketLimit, err := h.raffleSvc.GetRaffleTicketLimit(c.Context(), raffle.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println(sportAndLeagueID, res)
|
||||
// check raffle ticke count
|
||||
userTicketCount, err := h.raffleSvc.GetRaffleTicketCount(c.Context(), raffle.ID, int32(userID))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if userTicketCount == int64(raffleTicketLimit) {
|
||||
h.mongoLoggerSvc.Info("User reached max ticket count allowed for current raffle",
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Int64("raffleID", int64(raffle.ID)),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("companyID", companyID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
// empty raffle filter means there is no filter (all is allowed)
|
||||
hasFilter, err := h.raffleSvc.CheckSportRaffleHasFilter(c.Context(), raffle.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
foundValid := !hasFilter
|
||||
|
||||
// only require one sport and league combo to be valid to make the raffle ticket
|
||||
for _, sportAndLeagueID := range sportAndLeagueIDs {
|
||||
if foundValid {
|
||||
break
|
||||
}
|
||||
|
||||
res, err := h.raffleSvc.CheckValidSportRaffleFilter(c.Context(), raffle.ID, sportAndLeagueID[0], sportAndLeagueID[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
foundValid = foundValid || res
|
||||
}
|
||||
|
|
@ -289,7 +318,7 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
|||
UserID: int32(userID),
|
||||
}
|
||||
|
||||
_, err := h.raffleSvc.CreateRaffleTicket(c.Context(), raffleTicket)
|
||||
_, err = h.raffleSvc.CreateRaffleTicket(c.Context(), raffleTicket)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to create raffle ticket",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
|
|
@ -552,6 +581,25 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
var companyID domain.ValidInt64
|
||||
companyIDQuery := c.Query("company_id")
|
||||
if companyIDQuery != "" {
|
||||
companyIDParsed, err := strconv.ParseInt(companyIDQuery, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("invalid company_id format",
|
||||
zap.String("company_id", companyIDQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid company_id format")
|
||||
}
|
||||
companyID = domain.ValidInt64{
|
||||
Value: companyIDParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
bets, total, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
|
||||
IsShopBet: isShopBet,
|
||||
Query: searchString,
|
||||
|
|
@ -560,6 +608,7 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
Status: statusFilter,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
CompanyID: companyID,
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get all bets",
|
||||
|
|
@ -594,7 +643,6 @@ func (h *Handler) GetAllTenantBets(c *fiber.Ctx) error {
|
|||
h.BadRequestLogger().Error("invalid company id", zap.Any("company_id", companyID))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
role := c.Locals("role").(domain.Role)
|
||||
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
|
|
@ -608,7 +656,7 @@ func (h *Handler) GetAllTenantBets(c *fiber.Ctx) error {
|
|||
}
|
||||
var isShopBet domain.ValidBool
|
||||
isShopBetQuery := c.Query("is_shop")
|
||||
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
||||
if isShopBetQuery != "" {
|
||||
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("failed to parse is_shop_bet",
|
||||
|
|
@ -726,6 +774,8 @@ func (h *Handler) GetAllTenantBets(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/sport/bet/{id} [get]
|
||||
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
betID := c.Params("id")
|
||||
id, err := strconv.ParseInt(betID, 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -751,6 +801,15 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
|||
|
||||
res := domain.ConvertBet(bet)
|
||||
|
||||
if companyID.Valid && bet.CompanyID != companyID.Value {
|
||||
h.mongoLoggerSvc.Warn("Warn - Company is trying to access another companies bet",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusNotFound),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
|
||||
}
|
||||
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
||||
// zap.Int64("betID", id),
|
||||
// zap.Int("status_code", fiber.StatusOK),
|
||||
|
|
|
|||
|
|
@ -611,6 +611,8 @@ func (h *Handler) GetAllBranches(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/search/branch [get]
|
||||
func (h *Handler) SearchBranch(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
// Get search query from request
|
||||
searchQuery := c.Query("q")
|
||||
if searchQuery == "" {
|
||||
|
|
@ -622,7 +624,7 @@ func (h *Handler) SearchBranch(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
// Call the service to search for branches
|
||||
branches, err := h.branchSvc.SearchBranchByName(c.Context(), searchQuery)
|
||||
branches, err := h.branchSvc.SearchBranchByName(c.Context(), searchQuery, companyID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to search branches",
|
||||
zap.String("query", searchQuery),
|
||||
|
|
|
|||
|
|
@ -227,11 +227,8 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), domain.UserFilter{
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
})
|
||||
cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), filter)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to get all cashiers",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
|
@ -82,17 +83,31 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
|||
AdminID: user.ID,
|
||||
WalletID: newWallet.ID,
|
||||
DeductedPercentage: req.DeductedPercentage,
|
||||
Slug: req.Slug,
|
||||
IsActive: req.IsActive,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, domain.ErrWalletIDDuplicate) {
|
||||
h.mongoLoggerSvc.Error("CreateCompanyReq failed to create company",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.String("name", req.Name),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return fiber.NewError(fiber.StatusBadRequest, "this admin already has a company assigned to him")
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Error("CreateCompanyReq failed to create company",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.String("name", req.Name),
|
||||
zap.String("Name", req.Name),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -361,11 +376,12 @@ func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
company, err := h.companySvc.UpdateCompany(c.Context(), domain.ConvertUpdateCompanyReq(req))
|
||||
err = h.companySvc.UpdateCompany(c.Context(), domain.ConvertUpdateCompanyReq(req, id))
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to update company",
|
||||
zap.Int64("companyID", id),
|
||||
zap.Any("req", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
|
|
@ -373,9 +389,7 @@ func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,62 @@ func (h *Handler) GetAllResults(c *fiber.Ctx) error {
|
|||
})
|
||||
}
|
||||
|
||||
// GetAllPreodds godoc
|
||||
// @Summary Get all preodds
|
||||
// @Description Fetches all EnetPulse pre-match odds stored in the database
|
||||
// @Tags EnetPulse - Preodds
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} domain.Response{data=[]domain.EnetpulsePreodds}
|
||||
// @Failure 502 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/enetpulse/preodds [get]
|
||||
func (h *Handler) GetAllPreodds(c *fiber.Ctx) error {
|
||||
// Call service
|
||||
preodds, err := h.enetPulseSvc.GetAllPreodds(c.Context())
|
||||
if err != nil {
|
||||
log.Println("GetAllPreodds error:", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch EnetPulse preodds",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "EnetPulse preodds fetched successfully",
|
||||
Data: preodds,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// GetFixturesWithPreodds godoc
|
||||
// @Summary Get fixtures with preodds
|
||||
// @Description Fetches all EnetPulse fixtures along with their associated pre-match odds
|
||||
// @Tags EnetPulse - Fixtures
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} domain.Response{data=[]domain.EnetpulseFixtureWithPreodds}
|
||||
// @Failure 502 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/enetpulse/fixtures/preodds [get]
|
||||
func (h *Handler) GetFixturesWithPreodds(c *fiber.Ctx) error {
|
||||
// Call service
|
||||
fixtures, err := h.enetPulseSvc.GetFixturesWithPreodds(c.Context())
|
||||
if err != nil {
|
||||
log.Println("GetFixturesWithPreodds error:", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch EnetPulse fixtures with preodds",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
// Return success response
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "EnetPulse fixtures with preodds fetched successfully",
|
||||
Data: fixtures,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Helper: parse comma-separated string into []int
|
||||
func parseIntSlice(input string) []int {
|
||||
|
|
|
|||
|
|
@ -135,6 +135,40 @@ func (h *Handler) GetAllEvents(c *fiber.Ctx) error {
|
|||
}
|
||||
}
|
||||
|
||||
isActiveQuery := c.Query("is_active")
|
||||
var isActive domain.ValidBool
|
||||
if isActiveQuery != "" {
|
||||
isActiveParsed, err := strconv.ParseBool(isActiveQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("Failed to parse isActive",
|
||||
zap.String("is_active", isActiveQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_active")
|
||||
}
|
||||
|
||||
isActive = domain.ValidBool{
|
||||
Value: isActiveParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
statusQuery := c.Query("status")
|
||||
var eventStatus domain.ValidEventStatus
|
||||
if statusQuery != "" {
|
||||
eventStatusParsed, err := domain.ParseEventStatus(statusQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("Failed to parse statusQuery",
|
||||
zap.String("is_featured", isFeaturedQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid event status string")
|
||||
}
|
||||
eventStatus = domain.ValidEventStatus{
|
||||
Value: eventStatusParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
events, total, err := h.eventSvc.GetAllEvents(
|
||||
c.Context(), domain.EventFilter{
|
||||
SportID: sportID,
|
||||
|
|
@ -146,6 +180,8 @@ func (h *Handler) GetAllEvents(c *fiber.Ctx) error {
|
|||
Offset: offset,
|
||||
CountryCode: countryCode,
|
||||
Featured: isFeatured,
|
||||
Active: isActive,
|
||||
Status: eventStatus,
|
||||
})
|
||||
|
||||
// fmt.Printf("League ID: %v", leagueID)
|
||||
|
|
@ -234,22 +270,27 @@ func (h *Handler) GetTenantUpcomingEvents(c *fiber.Ctx) error {
|
|||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
// firstStartTimeQuery := c.Query("first_start_time")
|
||||
// var firstStartTime domain.ValidTime
|
||||
// if firstStartTimeQuery != "" {
|
||||
// firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||
// if err != nil {
|
||||
// h.BadRequestLogger().Info("invalid start_time format",
|
||||
// zap.String("first_start_time", firstStartTimeQuery),
|
||||
// zap.Error(err),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
// }
|
||||
// firstStartTime = domain.ValidTime{
|
||||
// Value: firstStartTimeParsed,
|
||||
// Valid: true,
|
||||
// }
|
||||
// }
|
||||
firstStartTimeQuery := c.Query("first_start_time")
|
||||
var firstStartTime domain.ValidTime
|
||||
if firstStartTimeQuery != "" {
|
||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid start_time format",
|
||||
zap.String("first_start_time", firstStartTimeQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
firstStartTime = domain.ValidTime{
|
||||
Value: firstStartTimeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
} else {
|
||||
firstStartTime = domain.ValidTime{
|
||||
Value: time.Now(),
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
lastStartTimeQuery := c.Query("last_start_time")
|
||||
var lastStartTime domain.ValidTime
|
||||
|
|
@ -297,10 +338,7 @@ func (h *Handler) GetTenantUpcomingEvents(c *fiber.Ctx) error {
|
|||
SportID: sportID,
|
||||
LeagueID: leagueID,
|
||||
Query: searchString,
|
||||
FirstStartTime: domain.ValidTime{
|
||||
Value: time.Now(),
|
||||
Valid: true,
|
||||
},
|
||||
FirstStartTime: firstStartTime,
|
||||
LastStartTime: lastStartTime,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
|
|
@ -334,6 +372,200 @@ func (h *Handler) GetTenantUpcomingEvents(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
|
||||
// @Summary Retrieve all upcoming events with settings
|
||||
// @Description Retrieve all upcoming events settings from the database
|
||||
// @Tags prematch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "Page number"
|
||||
// @Param page_size query int false "Page size"
|
||||
// @Param league_id query string false "League ID Filter"
|
||||
// @Param sport_id query string false "Sport ID Filter"
|
||||
// @Param cc query string false "Country Code Filter"
|
||||
// @Param first_start_time query string false "Start Time"
|
||||
// @Param last_start_time query string false "End Time"
|
||||
// @Success 200 {array} domain.BaseEvent
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/events [get]
|
||||
func (h *Handler) GetTenantEvents(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
limit := domain.ValidInt32{
|
||||
Value: int32(pageSize),
|
||||
Valid: true,
|
||||
}
|
||||
offset := domain.ValidInt32{
|
||||
Value: int32(page - 1),
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
leagueIDQuery := c.Query("league_id")
|
||||
var leagueID domain.ValidInt64
|
||||
if leagueIDQuery != "" {
|
||||
leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("invalid league id",
|
||||
zap.String("league_id", leagueIDQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
leagueID = domain.ValidInt64{
|
||||
Value: leagueIDInt,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
sportIDQuery := c.Query("sport_id")
|
||||
var sportID domain.ValidInt32
|
||||
if sportIDQuery != "" {
|
||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid sport id",
|
||||
zap.String("sportID", sportIDQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid sport id")
|
||||
}
|
||||
sportID = domain.ValidInt32{
|
||||
Value: int32(sportIDint),
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
firstStartTimeQuery := c.Query("first_start_time")
|
||||
var firstStartTime domain.ValidTime
|
||||
if firstStartTimeQuery != "" {
|
||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid start_time format",
|
||||
zap.String("first_start_time", firstStartTimeQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
firstStartTime = domain.ValidTime{
|
||||
Value: firstStartTimeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
lastStartTimeQuery := c.Query("last_start_time")
|
||||
var lastStartTime domain.ValidTime
|
||||
if lastStartTimeQuery != "" {
|
||||
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid last_start_time format",
|
||||
zap.String("last_start_time", lastStartTimeQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
lastStartTime = domain.ValidTime{
|
||||
Value: lastStartTimeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
countryCodeQuery := c.Query("cc")
|
||||
countryCode := domain.ValidString{
|
||||
Value: countryCodeQuery,
|
||||
Valid: countryCodeQuery != "",
|
||||
}
|
||||
|
||||
isFeaturedQuery := c.Query("is_featured")
|
||||
var isFeatured domain.ValidBool
|
||||
if isFeaturedQuery != "" {
|
||||
isFeaturedParsed, err := strconv.ParseBool(isFeaturedQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("Failed to parse isFeatured",
|
||||
zap.String("is_featured", isFeaturedQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_featured")
|
||||
}
|
||||
|
||||
isFeatured = domain.ValidBool{
|
||||
Value: isFeaturedParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
isActiveQuery := c.Query("is_active")
|
||||
var isActive domain.ValidBool
|
||||
if isActiveQuery != "" {
|
||||
isActiveParsed, err := strconv.ParseBool(isActiveQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("Failed to parse isActive",
|
||||
zap.String("is_active", isActiveQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_active")
|
||||
}
|
||||
|
||||
isActive = domain.ValidBool{
|
||||
Value: isActiveParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
statusQuery := c.Query("status")
|
||||
var eventStatus domain.ValidEventStatus
|
||||
if statusQuery != "" {
|
||||
eventStatusParsed, err := domain.ParseEventStatus(statusQuery)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("Failed to parse statusQuery",
|
||||
zap.String("is_featured", isFeaturedQuery),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid event status string")
|
||||
}
|
||||
eventStatus = domain.ValidEventStatus{
|
||||
Value: eventStatusParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
events, total, err := h.eventSvc.GetEventsWithSettings(
|
||||
c.Context(), companyID.Value, domain.EventFilter{
|
||||
SportID: sportID,
|
||||
LeagueID: leagueID,
|
||||
Query: searchString,
|
||||
FirstStartTime: firstStartTime,
|
||||
LastStartTime: lastStartTime,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
CountryCode: countryCode,
|
||||
Featured: isFeatured,
|
||||
Status: eventStatus,
|
||||
Active: isActive,
|
||||
})
|
||||
|
||||
// fmt.Printf("League ID: %v", leagueID)
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to retrieve all upcoming events",
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertEventWithSettingResList(events)
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", res, nil, page, int(total))
|
||||
|
||||
}
|
||||
|
||||
type TopLeaguesRes struct {
|
||||
Leagues []TopLeague `json:"leagues"`
|
||||
}
|
||||
|
|
@ -483,6 +715,145 @@ func (h *Handler) GetTenantEventByID(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
|
||||
// @Summary Retrieve bet outcomes by event id
|
||||
// @Description Retrieve bet outcomes by event id
|
||||
// @Tags prematch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "ID"
|
||||
// @Success 200 {object} domain.BaseEvent
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/events/{id}/bets [get]
|
||||
func (h *Handler) GetTenantBetsByEventID(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
idStr := c.Params("id")
|
||||
eventID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing id")
|
||||
}
|
||||
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
limit := domain.ValidInt32{
|
||||
Value: int32(pageSize),
|
||||
Valid: true,
|
||||
}
|
||||
offset := domain.ValidInt32{
|
||||
Value: int32(page - 1),
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
statusQuery := c.Params("status")
|
||||
var status domain.ValidOutcomeStatus
|
||||
if statusQuery != "" {
|
||||
statusIntParse, err := strconv.ParseInt(statusQuery, 10, 32)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status query")
|
||||
}
|
||||
|
||||
statusParsed, err := domain.ParseOutcomeStatus(int(statusIntParse))
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status query")
|
||||
}
|
||||
|
||||
status = domain.ValidOutcomeStatus{
|
||||
Value: statusParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
res, total, err := h.betSvc.GetBetOutcomeViewByEventID(c.Context(), eventID, domain.BetOutcomeViewFilter{
|
||||
OutcomeStatus: status,
|
||||
CompanyID: companyID,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to get upcoming event by id",
|
||||
zap.Int64("eventID", eventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Bet Outcomes retrieved successfully", res, nil, page, int(total))
|
||||
}
|
||||
|
||||
// @Summary Retrieve bet outcomes by event id
|
||||
// @Description Retrieve bet outcomes by event id
|
||||
// @Tags prematch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "ID"
|
||||
// @Success 200 {object} domain.BaseEvent
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/events/{id}/bets [get]
|
||||
func (h *Handler) GetBetsByEventID(c *fiber.Ctx) error {
|
||||
idStr := c.Params("id")
|
||||
eventID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing id")
|
||||
}
|
||||
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
limit := domain.ValidInt32{
|
||||
Value: int32(pageSize),
|
||||
Valid: true,
|
||||
}
|
||||
offset := domain.ValidInt32{
|
||||
Value: int32(page - 1),
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
statusQuery := c.Params("status")
|
||||
var status domain.ValidOutcomeStatus
|
||||
if statusQuery != "" {
|
||||
statusIntParse, err := strconv.ParseInt(statusQuery, 10, 32)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status query")
|
||||
}
|
||||
|
||||
statusParsed, err := domain.ParseOutcomeStatus(int(statusIntParse))
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status query")
|
||||
}
|
||||
|
||||
status = domain.ValidOutcomeStatus{
|
||||
Value: statusParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
res, total, err := h.betSvc.GetBetOutcomeViewByEventID(c.Context(), eventID, domain.BetOutcomeViewFilter{
|
||||
OutcomeStatus: status,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to get upcoming event by id",
|
||||
zap.Int64("eventID", eventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Bet Outcomes retrieved successfully", res, nil, page, int(total))
|
||||
}
|
||||
|
||||
type UpdateEventStatusReq struct {
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +892,7 @@ func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error {
|
|||
type UpdateEventSettingsReq struct {
|
||||
Featured *bool `json:"is_featured" example:"true"`
|
||||
IsActive *bool `json:"is_active" example:"true"`
|
||||
WinningUpperLimit *int `json:"winning_upper_limit" example:"10000"`
|
||||
WinningUpperLimit *int64 `json:"winning_upper_limit" example:"10000"`
|
||||
}
|
||||
|
||||
// UpdateEventSettings godoc
|
||||
|
|
@ -534,8 +905,72 @@ type UpdateEventSettingsReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/events/{id}/settings [put]
|
||||
// @Router /api/v1/events/{id}/settings [put]
|
||||
func (h *Handler) UpdateEventSettings(c *fiber.Ctx) error {
|
||||
eventIDStr := c.Params("id")
|
||||
|
||||
eventID, err := strconv.ParseInt(eventIDStr, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Error("invalid event id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid event id")
|
||||
}
|
||||
|
||||
var req UpdateEventSettingsReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id",
|
||||
zap.Int64("eventID", eventID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Int64("eventID", eventID),
|
||||
zap.Any("is_featured", req.Featured),
|
||||
zap.Any("is_active", req.IsActive),
|
||||
zap.Any("winning_upper_limit", req.WinningUpperLimit),
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Error("Failed to update event settings",
|
||||
append(logFields, zap.String("errMsg", errMsg))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.eventSvc.UpdateGlobalEventSettings(c.Context(), domain.UpdateGlobalEventSettings{
|
||||
EventID: eventID,
|
||||
IsFeatured: domain.ConvertBoolPtr(req.Featured),
|
||||
IsActive: domain.ConvertBoolPtr(req.IsActive),
|
||||
WinningUpperLimit: domain.ConvertInt64Ptr(req.WinningUpperLimit),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to update event settings", append(logFields, zap.Error(err))...)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
// UpdateTenantEventSettings godoc
|
||||
// @Summary update the event settings
|
||||
// @Description Update the event settings
|
||||
// @Tags event
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Event ID"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/events/{id}/settings [put]
|
||||
func (h *Handler) UpdateTenantEventSettings(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
|
|
@ -579,12 +1014,12 @@ func (h *Handler) UpdateEventSettings(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.eventSvc.UpdateEventSettings(c.Context(), domain.CreateEventSettings{
|
||||
err = h.eventSvc.UpdateTenantEventSettings(c.Context(), domain.UpdateTenantEventSettings{
|
||||
CompanyID: companyID.Value,
|
||||
EventID: eventID,
|
||||
IsFeatured: domain.ConvertBoolPtr(req.Featured),
|
||||
IsActive: domain.ConvertBoolPtr(req.IsActive),
|
||||
WinningUpperLimit: domain.ConvertIntPtr(req.WinningUpperLimit),
|
||||
WinningUpperLimit: domain.ConvertInt64Ptr(req.WinningUpperLimit),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
|
||||
limit := domain.ValidInt64{
|
||||
Value: int64(pageSize),
|
||||
Valid: pageSize == 0,
|
||||
Valid: pageSize != 0,
|
||||
}
|
||||
offset := domain.ValidInt64{
|
||||
Value: int64(page - 1),
|
||||
|
|
@ -54,7 +54,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
sportIDQuery := c.Query("sport_id")
|
||||
var sportID domain.ValidInt32
|
||||
if sportIDQuery != "" {
|
||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||
sportIDint, err := strconv.ParseInt(sportIDQuery, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid sport id",
|
||||
zap.String("sport_id", sportIDQuery),
|
||||
|
|
@ -86,7 +86,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
zap.Bool("sport_id_valid", sportID.Valid),
|
||||
}
|
||||
|
||||
leagues, err := h.leagueSvc.GetAllLeagues(c.Context(), domain.LeagueFilter{
|
||||
leagues, total, err := h.leagueSvc.GetAllLeagues(c.Context(), domain.LeagueFilter{
|
||||
CountryCode: countryCode,
|
||||
IsActive: isActive,
|
||||
SportID: sportID,
|
||||
|
|
@ -104,7 +104,7 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
|
||||
res := domain.ConvertBaseLeagueResList(leagues)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All leagues retrieved", res, nil)
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "All leagues retrieved successfully", res, nil, page, int(total))
|
||||
}
|
||||
|
||||
// GetAllLeaguesForTenant godoc
|
||||
|
|
@ -156,7 +156,7 @@ func (h *Handler) GetAllLeaguesForTenant(c *fiber.Ctx) error {
|
|||
sportIDQuery := c.Query("sport_id")
|
||||
var sportID domain.ValidInt32
|
||||
if sportIDQuery != "" {
|
||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||
sportIDint, err := strconv.ParseInt(sportIDQuery, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("invalid sport id",
|
||||
zap.String("sport_id", sportIDQuery),
|
||||
|
|
@ -235,7 +235,7 @@ func (h *Handler) SetLeagueActive(c *fiber.Ctx) error {
|
|||
if leagueIdStr == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing league id")
|
||||
}
|
||||
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||
leagueId, err := strconv.ParseInt(leagueIdStr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
|
@ -266,7 +266,7 @@ func (h *Handler) SetLeagueActive(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.leagueSvc.SaveLeagueSettings(c.Context(), domain.CreateLeagueSettings{
|
||||
LeagueID: int64(leagueId),
|
||||
LeagueID: leagueId,
|
||||
CompanyID: companyID.Value,
|
||||
IsActive: domain.ValidBool{
|
||||
Value: req.IsActive,
|
||||
|
|
@ -308,7 +308,7 @@ func (h *Handler) SetLeagueFeatured(c *fiber.Ctx) error {
|
|||
if leagueIdStr == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing league id")
|
||||
}
|
||||
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||
leagueId, err := strconv.ParseInt(leagueIdStr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ func (h *Handler) SetLeagueFeatured(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
err = h.leagueSvc.SaveLeagueSettings(c.Context(), domain.CreateLeagueSettings{
|
||||
LeagueID: int64(leagueId),
|
||||
LeagueID: leagueId,
|
||||
CompanyID: companyID.Value,
|
||||
IsFeatured: domain.ValidBool{
|
||||
Value: req.IsFeatured,
|
||||
|
|
@ -351,3 +351,45 @@ func (h *Handler) SetLeagueFeatured(c *fiber.Ctx) error {
|
|||
h.SuccessResLogger().Info("League Featured has been successfully updated", queryLogFields...)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateGlobalLeagueSetting(c *fiber.Ctx) error {
|
||||
leagueIdStr := c.Params("id")
|
||||
if leagueIdStr == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing league id")
|
||||
}
|
||||
leagueId, err := strconv.ParseInt(leagueIdStr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
||||
var req domain.UpdateLeagueSettingsReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("UpdateLeagueSettingsReq failed to parse request body", zap.String("league_id", leagueIdStr), zap.Error(err))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse request body:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Info("Failed to validate UpdateLeagueSettingsReq", zap.Error(err))
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
|
||||
}
|
||||
|
||||
err = h.leagueSvc.UpdateGlobalLeagueSettings(c.Context(), domain.UpdateGlobalLeagueSettings{
|
||||
ID: leagueId,
|
||||
DefaultIsActive: domain.ConvertBoolPtr(req.IsActive),
|
||||
DefaultIsFeatured: domain.ConvertBoolPtr(req.IsFeatured),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to update league", zap.Error(err), zap.String("leagueId", leagueIdStr))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update league:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,7 +276,6 @@ func (h *Handler) GetTenantOddsByUpcomingID(c *fiber.Ctx) error {
|
|||
zap.Int64("company_id", companyID.Value),
|
||||
}
|
||||
|
||||
|
||||
eventIDStr := c.Params("upcoming_id")
|
||||
eventID, err := strconv.ParseInt(eventIDStr, 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -309,7 +308,7 @@ func (h *Handler) GetTenantOddsByUpcomingID(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
|
||||
func (h *Handler) SaveOddsSetting(c *fiber.Ctx) error {
|
||||
func (h *Handler) SaveTenantOddsSetting(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
|
|
@ -318,7 +317,7 @@ func (h *Handler) SaveOddsSetting(c *fiber.Ctx) error {
|
|||
var req domain.CreateOddMarketSettingsReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id",
|
||||
h.BadRequestLogger().Info("Failed to parse CreateOddMarketSettingsReq",
|
||||
zap.Int64("CompanyID", companyID.Value),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
|
@ -337,7 +336,7 @@ func (h *Handler) SaveOddsSetting(c *fiber.Ctx) error {
|
|||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Error("Failed to insert odd settings",
|
||||
h.BadRequestLogger().Error("Failed to validate insert odd settings",
|
||||
append(logFields, zap.String("errMsg", errMsg))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
|
|
@ -354,3 +353,175 @@ func (h *Handler) SaveOddsSetting(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Odds Settings saved successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
func (h *Handler) SaveOddSettings(c *fiber.Ctx) error {
|
||||
var req domain.UpdateGlobalOddMarketSettingsReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse CreateOddMarketSettingsReq",
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Any("is_active", req.IsActive),
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Error("Failed to validate insert odd settings",
|
||||
append(logFields, zap.String("errMsg", errMsg))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err := h.prematchSvc.UpdateGlobalOddsSetting(c.Context(), domain.UpdateGlobalOddMarketSettings{
|
||||
OddMarketID: req.OddMarketID,
|
||||
IsActive: domain.ConvertBoolPtr(req.IsActive),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logFields = append(logFields, zap.Error(err))
|
||||
h.InternalServerErrorLogger().Error("Failed to save odds settings", append(logFields, zap.Error(err))...)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to save odds settings"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Odds Settings saved successfully", nil, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) RemoveOddsSettings(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
idStr := c.Params("id")
|
||||
oddID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse odd id", zap.String("id", idStr))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing id")
|
||||
}
|
||||
|
||||
err = h.prematchSvc.DeleteCompanyOddsSettingByOddMarketID(c.Context(), companyID.Value, oddID)
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to retrieve odds", zap.Error(err))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to remove odds settings"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Odds settings successfully removed ", nil, nil)
|
||||
}
|
||||
func (h *Handler) RemoveAllOddsSettings(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
err := h.prematchSvc.DeleteAllCompanyOddsSetting(c.Context(), companyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to remove all odd settings", zap.Int64("company_id", companyID.Value), zap.Error(err))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to remove all odds settings"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Odds settings successfully removed ", nil, nil)
|
||||
}
|
||||
|
||||
type UpdateAllBetStatusByOddIDReq struct {
|
||||
Status domain.OutcomeStatus `json:"status"`
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateAllBetOutcomeStatusByOddID(c *fiber.Ctx) error {
|
||||
|
||||
idStr := c.Params("id")
|
||||
oddID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse odd_id", zap.String("id", idStr))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing id")
|
||||
}
|
||||
|
||||
var req UpdateAllBetStatusByOddIDReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id",
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Any("status", req.Status),
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Error("Failed to insert odd settings",
|
||||
append(logFields, zap.String("errMsg", errMsg))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
_, err = h.betSvc.UpdateBetOutcomeStatusForOddId(c.Context(), oddID, req.Status)
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to update bet status by odd id",
|
||||
zap.Int64("oddID", oddID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Updated All Bet Outcome Status Successfully", nil, nil)
|
||||
}
|
||||
type BulkUpdateAllBetStatusByOddIDsReq struct {
|
||||
OddIDs []int64 `json:"odd_ids"`
|
||||
Status domain.OutcomeStatus `json:"status"`
|
||||
}
|
||||
|
||||
func (h *Handler) BulkUpdateAllBetOutcomeStatusByOddID(c *fiber.Ctx) error {
|
||||
var req BulkUpdateAllBetStatusByOddIDsReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.BadRequestLogger().Info("Failed to parse event id",
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
logFields := []zap.Field{
|
||||
zap.Int64s("odd_ids", req.OddIDs),
|
||||
zap.Any("status", req.Status),
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.BadRequestLogger().Error("Failed to insert odd settings",
|
||||
append(logFields, zap.String("errMsg", errMsg))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err := h.betSvc.BulkUpdateBetOutcomeStatusForOddIds(c.Context(), req.OddIDs, req.Status)
|
||||
|
||||
if err != nil {
|
||||
h.InternalServerErrorLogger().Error("Failed to bulk update bet status by odd ids",
|
||||
append(logFields, zap.Error(err))...,
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bulk Updated All Bet Outcome Status Successfully", nil, nil)
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user