fix: refactored bet to remove unnecessary fields

This commit is contained in:
Samuel Tariku 2025-07-09 21:48:36 +03:00
parent 75f2499bb1
commit d1770eceb6
30 changed files with 754 additions and 860 deletions

View File

@ -2,6 +2,7 @@
"cSpell.words": [ "cSpell.words": [
"Cashout", "Cashout",
"narg", "narg",
"notificationservice",
"sqlc" "sqlc"
] ]
} }

View File

@ -123,7 +123,7 @@ func main() {
companySvc := company.NewService(store) companySvc := company.NewService(store)
leagueSvc := league.New(store) leagueSvc := league.New(store)
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc) ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, logger, domain.MongoDBLogger) betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, *settingSvc, notificationSvc, logger, domain.MongoDBLogger)
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc) resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
bonusSvc := bonus.NewService(store) bonusSvc := bonus.NewService(store)
referalRepo := repository.NewReferralRepository(store) referalRepo := repository.NewReferralRepository(store)

View File

@ -45,23 +45,13 @@ CREATE TABLE IF NOT EXISTS bets (
amount BIGINT NOT NULL, amount BIGINT NOT NULL,
total_odds REAL NOT NULL, total_odds REAL NOT NULL,
status INT NOT NULL, status INT NOT NULL,
full_name VARCHAR(255) NOT NULL, user_id BIGINT NOT NULL,
phone_number VARCHAR(255) NOT NULL,
company_id BIGINT,
branch_id BIGINT,
user_id BIGINT,
cashed_out BOOLEAN DEFAULT FALSE NOT NULL,
cashout_id VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_shop_bet BOOLEAN NOT NULL, is_shop_bet BOOLEAN NOT NULL,
cashed_out BOOLEAN NOT NULL DEFAULT false,
outcomes_hash TEXT NOT NULL, outcomes_hash TEXT NOT NULL,
fast_code VARCHAR(10) NOT NULL, fast_code VARCHAR(10) NOT NULL,
UNIQUE(cashout_id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CHECK ( updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
user_id IS NOT NULL
OR branch_id IS NOT NULL
)
); );
CREATE TABLE IF NOT EXISTS tickets ( CREATE TABLE IF NOT EXISTS tickets (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
@ -260,7 +250,8 @@ CREATE TABLE events (
is_live BOOLEAN, is_live BOOLEAN,
status TEXT, status TEXT,
fetched_at TIMESTAMP DEFAULT now(), fetched_at TIMESTAMP DEFAULT now(),
source TEXT DEFAULT 'b365api' source TEXT DEFAULT 'b365api',
flagged BOOLEAN NOT NULL DEFAULT false
); );
CREATE TABLE odds ( CREATE TABLE odds (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
@ -347,10 +338,16 @@ CREATE TABLE IF NOT EXISTS supported_operations (
); );
CREATE VIEW bet_with_outcomes AS CREATE VIEW bet_with_outcomes AS
SELECT bets.*, 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
FROM bets FROM bets
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
GROUP BY bets.id; LEFT JOIN users ON bets.user_id = users.id
GROUP BY bets.id,
users.first_name,
users.last_name,
users.phone_number;
CREATE VIEW ticket_with_outcomes AS CREATE VIEW ticket_with_outcomes AS
SELECT tickets.*, SELECT tickets.*,
JSON_AGG(ticket_outcomes.*) AS outcomes JSON_AGG(ticket_outcomes.*) AS outcomes
@ -438,8 +435,7 @@ ADD CONSTRAINT unique_email UNIQUE (email),
ALTER TABLE refresh_tokens ALTER TABLE refresh_tokens
ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id); ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id);
ALTER TABLE bets ALTER TABLE bets
ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id), ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id);
ADD CONSTRAINT fk_bets_branches FOREIGN KEY (branch_id) REFERENCES branches(id);
ALTER TABLE wallets ALTER TABLE wallets
ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id), ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id),
ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB'; ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB';
@ -494,7 +490,7 @@ VALUES (
'Doe', 'Doe',
'john.doe@example.com', 'john.doe@example.com',
NULL, NULL,
crypt('password123', gen_salt('bf'))::bytea, crypt('password@123', gen_salt('bf'))::bytea,
'customer', 'customer',
TRUE, TRUE,
FALSE, FALSE,

View File

@ -1,12 +1,14 @@
CREATE TABLE IF NOT EXISTS reported_issues ( CREATE TABLE IF NOT EXISTS reported_issues (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
customer_id BIGINT NOT NULL, user_id BIGINT NOT NULL REFERENCES users(id),
user_role VARCHAR(255) NOT NULL,
subject TEXT NOT NULL, subject TEXT NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
issue_type TEXT NOT NULL, -- e.g., "deposit", "withdrawal", "bet", "technical" issue_type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending', -- pending, in_progress, resolved, rejected -- e.g., "deposit", "withdrawal", "bet", "technical"
status TEXT NOT NULL DEFAULT 'pending',
-- pending, in_progress, resolved, rejected
metadata JSONB, metadata JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );

View File

@ -3,17 +3,12 @@ INSERT INTO bets (
amount, amount,
total_odds, total_odds,
status, status,
full_name,
phone_number,
branch_id,
user_id, user_id,
is_shop_bet, is_shop_bet,
cashout_id,
company_id,
outcomes_hash, outcomes_hash,
fast_code fast_code
) )
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING *; RETURNING *;
-- name: CreateBetOutcome :copyfrom -- name: CreateBetOutcome :copyfrom
INSERT INTO bet_outcomes ( INSERT INTO bet_outcomes (
@ -50,14 +45,6 @@ VALUES (
SELECT * SELECT *
FROM bet_with_outcomes FROM bet_with_outcomes
wHERE ( wHERE (
branch_id = sqlc.narg('branch_id')
OR sqlc.narg('branch_id') IS NULL
)
AND (
company_id = sqlc.narg('company_id')
OR sqlc.narg('company_id') IS NULL
)
AND (
user_id = sqlc.narg('user_id') user_id = sqlc.narg('user_id')
OR sqlc.narg('user_id') IS NULL OR sqlc.narg('user_id') IS NULL
) )
@ -65,6 +52,10 @@ wHERE (
is_shop_bet = sqlc.narg('is_shop_bet') is_shop_bet = sqlc.narg('is_shop_bet')
OR sqlc.narg('is_shop_bet') IS NULL OR sqlc.narg('is_shop_bet') IS NULL
) )
AND (
cashed_out = sqlc.narg('cashed_out')
OR sqlc.narg('cashed_out') IS NULL
)
AND ( AND (
full_name ILIKE '%' || sqlc.narg('query') || '%' full_name ILIKE '%' || sqlc.narg('query') || '%'
OR phone_number ILIKE '%' || sqlc.narg('query') || '%' OR phone_number ILIKE '%' || sqlc.narg('query') || '%'
@ -82,14 +73,6 @@ wHERE (
SELECT * SELECT *
FROM bet_with_outcomes FROM bet_with_outcomes
WHERE id = $1; WHERE id = $1;
-- name: GetBetByCashoutID :one
SELECT *
FROM bet_with_outcomes
WHERE cashout_id = $1;
-- name: GetBetByBranchID :many
SELECT *
FROM bet_with_outcomes
WHERE branch_id = $1;
-- name: GetBetByUserID :many -- name: GetBetByUserID :many
SELECT * SELECT *
FROM bet_with_outcomes FROM bet_with_outcomes

View File

@ -126,45 +126,14 @@ SELECT id
FROM events FROM events
WHERE is_live = true; WHERE is_live = true;
-- name: GetAllUpcomingEvents :many -- name: GetAllUpcomingEvents :many
SELECT id, SELECT *
sport_id,
match_name,
home_team,
away_team,
home_team_id,
away_team_id,
home_kit_image,
away_kit_image,
league_id,
league_name,
league_cc,
start_time,
is_live,
status,
source,
fetched_at
FROM events FROM events
WHERE start_time > now() WHERE start_time > now()
AND is_live = false AND is_live = false
AND status = 'upcoming' AND status = 'upcoming'
ORDER BY start_time ASC; ORDER BY start_time ASC;
-- name: GetExpiredUpcomingEvents :many -- name: GetExpiredUpcomingEvents :many
SELECT events.id, SELECT events.*,
events.sport_id,
events.match_name,
events.home_team,
events.away_team,
events.home_team_id,
events.away_team_id,
events.home_kit_image,
events.away_kit_image,
events.league_id,
events.league_name,
events.start_time,
events.is_live,
events.status,
events.source,
events.fetched_at,
leagues.country_code as league_cc leagues.country_code as league_cc
FROM events FROM events
LEFT JOIN leagues ON leagues.id = league_id LEFT JOIN leagues ON leagues.id = league_id
@ -201,22 +170,7 @@ WHERE is_live = false
OR sqlc.narg('country_code') IS NULL OR sqlc.narg('country_code') IS NULL
); );
-- name: GetPaginatedUpcomingEvents :many -- name: GetPaginatedUpcomingEvents :many
SELECT events.id, SELECT events.*,
events.sport_id,
events.match_name,
events.home_team,
events.away_team,
events.home_team_id,
events.away_team_id,
events.home_kit_image,
events.away_kit_image,
events.league_id,
events.league_name,
events.start_time,
events.is_live,
events.status,
events.source,
events.fetched_at,
leagues.country_code as league_cc leagues.country_code as league_cc
FROM events FROM events
LEFT JOIN leagues ON leagues.id = league_id LEFT JOIN leagues ON leagues.id = league_id
@ -246,23 +200,7 @@ WHERE start_time > now()
ORDER BY start_time ASC ORDER BY start_time ASC
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset'); LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetUpcomingByID :one -- name: GetUpcomingByID :one
SELECT id, SELECT *
sport_id,
match_name,
home_team,
away_team,
home_team_id,
away_team_id,
home_kit_image,
away_kit_image,
league_id,
league_name,
league_cc,
start_time,
is_live,
status,
source,
fetched_at
FROM events FROM events
WHERE id = $1 WHERE id = $1
AND is_live = false AND is_live = false
@ -271,9 +209,12 @@ LIMIT 1;
-- name: UpdateMatchResult :exec -- name: UpdateMatchResult :exec
UPDATE events UPDATE events
SET score = $1, SET score = $1,
status = $2, status = $2
fetched_at = NOW()
WHERE id = $3; WHERE id = $3;
-- name: UpdateFlagged :exec
UPDATE events
SET flagged = $1
WHERE id = $2;
-- name: DeleteEvent :exec -- name: DeleteEvent :exec
DELETE FROM events DELETE FROM events
WHERE id = $1; WHERE id = $1;

View File

@ -1,32 +1,37 @@
-- name: CreateReportedIssue :one -- name: CreateReportedIssue :one
INSERT INTO reported_issues ( INSERT INTO reported_issues (
customer_id, subject, description, issue_type, metadata user_id,
) VALUES ( user_role,
$1, $2, $3, $4, $5 subject,
) description,
issue_type,
metadata
)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *; RETURNING *;
-- name: ListReportedIssues :many -- name: ListReportedIssues :many
SELECT * FROM reported_issues SELECT *
FROM reported_issues
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT $1 OFFSET $2; LIMIT $1 OFFSET $2;
-- name: ListReportedIssuesByUser :many
-- name: ListReportedIssuesByCustomer :many SELECT *
SELECT * FROM reported_issues FROM reported_issues
WHERE customer_id = $1 WHERE user_id = $1
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT $2 OFFSET $3; LIMIT $2 OFFSET $3;
-- name: CountReportedIssues :one -- name: CountReportedIssues :one
SELECT COUNT(*) FROM reported_issues; SELECT COUNT(*)
FROM reported_issues;
-- name: CountReportedIssuesByCustomer :one -- name: CountReportedIssuesByUser :one
SELECT COUNT(*) FROM reported_issues WHERE customer_id = $1; SELECT COUNT(*)
FROM reported_issues
WHERE user_id = $1;
-- name: UpdateReportedIssueStatus :exec -- name: UpdateReportedIssueStatus :exec
UPDATE reported_issues UPDATE reported_issues
SET status = $2, updated_at = NOW() SET status = $2,
updated_at = NOW()
WHERE id = $1; WHERE id = $1;
-- name: DeleteReportedIssue :exec -- name: DeleteReportedIssue :exec
DELETE FROM reported_issues WHERE id = $1; DELETE FROM reported_issues
WHERE id = $1;

View File

@ -17,28 +17,60 @@ FROM bets
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to') WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
AND status = 5; AND status = 5;
-- name: GetCompanyWiseReport :many -- name: GetCompanyWiseReport :many
SELECT SELECT b.company_id,
b.company_id,
c.name AS company_name, c.name AS company_name,
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(b.amount), 0) AS total_cash_made, COALESCE(SUM(b.amount), 0) AS total_cash_made,
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out, COALESCE(
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs SUM(
FROM bets b CASE
JOIN companies c ON b.company_id = c.id WHEN b.cashed_out THEN b.amount
ELSE 0
END
),
0
) AS total_cash_out,
COALESCE(
SUM(
CASE
WHEN b.status = 5 THEN b.amount
ELSE 0
END
),
0
) AS total_cash_backs
FROM shop_bet_detail b
JOIN companies c ON b.company_id = c.id
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to') WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
GROUP BY b.company_id, c.name; GROUP BY b.company_id,
c.name;
-- name: GetBranchWiseReport :many -- name: GetBranchWiseReport :many
SELECT SELECT b.branch_id,
b.branch_id,
br.name AS branch_name, br.name AS branch_name,
br.company_id, br.company_id,
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(b.amount), 0) AS total_cash_made, COALESCE(SUM(b.amount), 0) AS total_cash_made,
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out, COALESCE(
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs SUM(
FROM bets b CASE
JOIN branches br ON b.branch_id = br.id WHEN b.cashed_out THEN b.amount
ELSE 0
END
),
0
) AS total_cash_out,
COALESCE(
SUM(
CASE
WHEN b.status = 5 THEN b.amount
ELSE 0
END
),
0
) AS total_cash_backs
FROM shop_bet_detail b
JOIN branches br ON b.branch_id = br.id
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to') WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
GROUP BY b.branch_id, br.name, br.company_id; GROUP BY b.branch_id,
br.name,
br.company_id;

View File

@ -16,31 +16,21 @@ INSERT INTO bets (
amount, amount,
total_odds, total_odds,
status, status,
full_name,
phone_number,
branch_id,
user_id, user_id,
is_shop_bet, is_shop_bet,
cashout_id,
company_id,
outcomes_hash, outcomes_hash,
fast_code fast_code
) )
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code RETURNING id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, created_at, updated_at
` `
type CreateBetParams struct { type CreateBetParams struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Status int32 `json:"status"` Status int32 `json:"status"`
FullName string `json:"full_name"` UserID int64 `json:"user_id"`
PhoneNumber string `json:"phone_number"`
BranchID pgtype.Int8 `json:"branch_id"`
UserID pgtype.Int8 `json:"user_id"`
IsShopBet bool `json:"is_shop_bet"` IsShopBet bool `json:"is_shop_bet"`
CashoutID string `json:"cashout_id"`
CompanyID pgtype.Int8 `json:"company_id"`
OutcomesHash string `json:"outcomes_hash"` OutcomesHash string `json:"outcomes_hash"`
FastCode string `json:"fast_code"` FastCode string `json:"fast_code"`
} }
@ -50,13 +40,8 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
arg.Amount, arg.Amount,
arg.TotalOdds, arg.TotalOdds,
arg.Status, arg.Status,
arg.FullName,
arg.PhoneNumber,
arg.BranchID,
arg.UserID, arg.UserID,
arg.IsShopBet, arg.IsShopBet,
arg.CashoutID,
arg.CompanyID,
arg.OutcomesHash, arg.OutcomesHash,
arg.FastCode, arg.FastCode,
) )
@ -66,18 +51,13 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Status, &i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID, &i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet, &i.IsShopBet,
&i.CashedOut,
&i.OutcomesHash, &i.OutcomesHash,
&i.FastCode, &i.FastCode,
&i.CreatedAt,
&i.UpdatedAt,
) )
return i, err return i, err
} }
@ -119,44 +99,39 @@ func (q *Queries) DeleteBetOutcome(ctx context.Context, betID int64) error {
} }
const GetAllBets = `-- name: GetAllBets :many const GetAllBets = `-- name: GetAllBets :many
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes SELECT id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, created_at, updated_at, full_name, phone_number, outcomes
FROM bet_with_outcomes FROM bet_with_outcomes
wHERE ( wHERE (
branch_id = $1 user_id = $1
OR $1 IS NULL OR $1 IS NULL
) )
AND ( AND (
company_id = $2 is_shop_bet = $2
OR $2 IS NULL OR $2 IS NULL
) )
AND ( AND (
user_id = $3 cashed_out = $3
OR $3 IS NULL OR $3 IS NULL
) )
AND ( AND (
is_shop_bet = $4 full_name ILIKE '%' || $4 || '%'
OR phone_number ILIKE '%' || $4 || '%'
OR $4 IS NULL OR $4 IS NULL
) )
AND ( AND (
full_name ILIKE '%' || $5 || '%' created_at > $5
OR phone_number ILIKE '%' || $5 || '%'
OR $5 IS NULL OR $5 IS NULL
) )
AND ( AND (
created_at > $6 created_at < $6
OR $6 IS NULL OR $6 IS NULL
) )
AND (
created_at < $7
OR $7 IS NULL
)
` `
type GetAllBetsParams struct { type GetAllBetsParams struct {
BranchID pgtype.Int8 `json:"branch_id"`
CompanyID pgtype.Int8 `json:"company_id"`
UserID pgtype.Int8 `json:"user_id"` UserID pgtype.Int8 `json:"user_id"`
IsShopBet pgtype.Bool `json:"is_shop_bet"` IsShopBet pgtype.Bool `json:"is_shop_bet"`
CashedOut pgtype.Bool `json:"cashed_out"`
Query pgtype.Text `json:"query"` Query pgtype.Text `json:"query"`
CreatedBefore pgtype.Timestamp `json:"created_before"` CreatedBefore pgtype.Timestamp `json:"created_before"`
CreatedAfter pgtype.Timestamp `json:"created_after"` CreatedAfter pgtype.Timestamp `json:"created_after"`
@ -164,10 +139,9 @@ type GetAllBetsParams struct {
func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) { func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) {
rows, err := q.db.Query(ctx, GetAllBets, rows, err := q.db.Query(ctx, GetAllBets,
arg.BranchID,
arg.CompanyID,
arg.UserID, arg.UserID,
arg.IsShopBet, arg.IsShopBet,
arg.CashedOut,
arg.Query, arg.Query,
arg.CreatedBefore, arg.CreatedBefore,
arg.CreatedAfter, arg.CreatedAfter,
@ -184,18 +158,15 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Status, &i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID, &i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet, &i.IsShopBet,
&i.CashedOut,
&i.OutcomesHash, &i.OutcomesHash,
&i.FastCode, &i.FastCode,
&i.CreatedAt,
&i.UpdatedAt,
&i.FullName,
&i.PhoneNumber,
&i.Outcomes, &i.Outcomes,
); err != nil { ); err != nil {
return nil, err return nil, err
@ -208,83 +179,8 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
return items, nil return items, nil
} }
const GetBetByBranchID = `-- name: GetBetByBranchID :many
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes
FROM bet_with_outcomes
WHERE branch_id = $1
`
func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([]BetWithOutcome, error) {
rows, err := q.db.Query(ctx, GetBetByBranchID, branchID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []BetWithOutcome
for rows.Next() {
var i BetWithOutcome
if err := rows.Scan(
&i.ID,
&i.Amount,
&i.TotalOdds,
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet,
&i.OutcomesHash,
&i.FastCode,
&i.Outcomes,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetBetByCashoutID = `-- name: GetBetByCashoutID :one
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes
FROM bet_with_outcomes
WHERE cashout_id = $1
`
func (q *Queries) GetBetByCashoutID(ctx context.Context, cashoutID string) (BetWithOutcome, error) {
row := q.db.QueryRow(ctx, GetBetByCashoutID, cashoutID)
var i BetWithOutcome
err := row.Scan(
&i.ID,
&i.Amount,
&i.TotalOdds,
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet,
&i.OutcomesHash,
&i.FastCode,
&i.Outcomes,
)
return i, err
}
const GetBetByFastCode = `-- name: GetBetByFastCode :one const GetBetByFastCode = `-- name: GetBetByFastCode :one
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes SELECT id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, created_at, updated_at, full_name, phone_number, outcomes
FROM bet_with_outcomes FROM bet_with_outcomes
WHERE fast_code = $1 WHERE fast_code = $1
LIMIT 1 LIMIT 1
@ -298,25 +194,22 @@ func (q *Queries) GetBetByFastCode(ctx context.Context, fastCode string) (BetWit
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Status, &i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID, &i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet, &i.IsShopBet,
&i.CashedOut,
&i.OutcomesHash, &i.OutcomesHash,
&i.FastCode, &i.FastCode,
&i.CreatedAt,
&i.UpdatedAt,
&i.FullName,
&i.PhoneNumber,
&i.Outcomes, &i.Outcomes,
) )
return i, err return i, err
} }
const GetBetByID = `-- name: GetBetByID :one const GetBetByID = `-- name: GetBetByID :one
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes SELECT id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, created_at, updated_at, full_name, phone_number, outcomes
FROM bet_with_outcomes FROM bet_with_outcomes
WHERE id = $1 WHERE id = $1
` `
@ -329,30 +222,27 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Status, &i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID, &i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet, &i.IsShopBet,
&i.CashedOut,
&i.OutcomesHash, &i.OutcomesHash,
&i.FastCode, &i.FastCode,
&i.CreatedAt,
&i.UpdatedAt,
&i.FullName,
&i.PhoneNumber,
&i.Outcomes, &i.Outcomes,
) )
return i, err return i, err
} }
const GetBetByUserID = `-- name: GetBetByUserID :many const GetBetByUserID = `-- name: GetBetByUserID :many
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, outcomes SELECT id, amount, total_odds, status, user_id, is_shop_bet, cashed_out, outcomes_hash, fast_code, created_at, updated_at, full_name, phone_number, outcomes
FROM bet_with_outcomes FROM bet_with_outcomes
WHERE user_id = $1 WHERE user_id = $1
` `
func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]BetWithOutcome, error) { func (q *Queries) GetBetByUserID(ctx context.Context, userID int64) ([]BetWithOutcome, error) {
rows, err := q.db.Query(ctx, GetBetByUserID, userID) rows, err := q.db.Query(ctx, GetBetByUserID, userID)
if err != nil { if err != nil {
return nil, err return nil, err
@ -366,18 +256,15 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Status, &i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID, &i.UserID,
&i.CashedOut,
&i.CashoutID,
&i.CreatedAt,
&i.UpdatedAt,
&i.IsShopBet, &i.IsShopBet,
&i.CashedOut,
&i.OutcomesHash, &i.OutcomesHash,
&i.FastCode, &i.FastCode,
&i.CreatedAt,
&i.UpdatedAt,
&i.FullName,
&i.PhoneNumber,
&i.Outcomes, &i.Outcomes,
); err != nil { ); err != nil {
return nil, err return nil, err
@ -393,12 +280,12 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
const GetBetCount = `-- name: GetBetCount :one const GetBetCount = `-- name: GetBetCount :one
SELECT COUNT(*) SELECT COUNT(*)
FROM bets FROM bets
where user_id = $1 WHERE user_id = $1
AND outcomes_hash = $2 AND outcomes_hash = $2
` `
type GetBetCountParams struct { type GetBetCountParams struct {
UserID pgtype.Int8 `json:"user_id"` UserID int64 `json:"user_id"`
OutcomesHash string `json:"outcomes_hash"` OutcomesHash string `json:"outcomes_hash"`
} }

View File

@ -22,23 +22,7 @@ func (q *Queries) DeleteEvent(ctx context.Context, id string) error {
} }
const GetAllUpcomingEvents = `-- name: GetAllUpcomingEvents :many const GetAllUpcomingEvents = `-- name: GetAllUpcomingEvents :many
SELECT id, SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, league_cc, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, flagged
sport_id,
match_name,
home_team,
away_team,
home_team_id,
away_team_id,
home_kit_image,
away_kit_image,
league_id,
league_name,
league_cc,
start_time,
is_live,
status,
source,
fetched_at
FROM events FROM events
WHERE start_time > now() WHERE start_time > now()
AND is_live = false AND is_live = false
@ -46,35 +30,15 @@ WHERE start_time > now()
ORDER BY start_time ASC ORDER BY start_time ASC
` `
type GetAllUpcomingEventsRow struct { func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]Event, error) {
ID string `json:"id"`
SportID pgtype.Int4 `json:"sport_id"`
MatchName pgtype.Text `json:"match_name"`
HomeTeam pgtype.Text `json:"home_team"`
AwayTeam pgtype.Text `json:"away_team"`
HomeTeamID pgtype.Int4 `json:"home_team_id"`
AwayTeamID pgtype.Int4 `json:"away_team_id"`
HomeKitImage pgtype.Text `json:"home_kit_image"`
AwayKitImage pgtype.Text `json:"away_kit_image"`
LeagueID pgtype.Int4 `json:"league_id"`
LeagueName pgtype.Text `json:"league_name"`
LeagueCc pgtype.Text `json:"league_cc"`
StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
}
func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEventsRow, error) {
rows, err := q.db.Query(ctx, GetAllUpcomingEvents) rows, err := q.db.Query(ctx, GetAllUpcomingEvents)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []GetAllUpcomingEventsRow var items []Event
for rows.Next() { for rows.Next() {
var i GetAllUpcomingEventsRow var i Event
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.SportID, &i.SportID,
@ -89,10 +53,16 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
&i.LeagueName, &i.LeagueName,
&i.LeagueCc, &i.LeagueCc,
&i.StartTime, &i.StartTime,
&i.Score,
&i.MatchMinute,
&i.TimerStatus,
&i.AddedTime,
&i.MatchPeriod,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
&i.Source,
&i.Flagged,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -105,22 +75,7 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
} }
const GetExpiredUpcomingEvents = `-- name: GetExpiredUpcomingEvents :many const GetExpiredUpcomingEvents = `-- name: GetExpiredUpcomingEvents :many
SELECT events.id, SELECT events.id, events.sport_id, events.match_name, events.home_team, events.away_team, events.home_team_id, events.away_team_id, events.home_kit_image, events.away_kit_image, events.league_id, events.league_name, events.league_cc, events.start_time, events.score, events.match_minute, events.timer_status, events.added_time, events.match_period, events.is_live, events.status, events.fetched_at, events.source, events.flagged,
events.sport_id,
events.match_name,
events.home_team,
events.away_team,
events.home_team_id,
events.away_team_id,
events.home_kit_image,
events.away_kit_image,
events.league_id,
events.league_name,
events.start_time,
events.is_live,
events.status,
events.source,
events.fetched_at,
leagues.country_code as league_cc leagues.country_code as league_cc
FROM events FROM events
LEFT JOIN leagues ON leagues.id = league_id LEFT JOIN leagues ON leagues.id = league_id
@ -144,12 +99,19 @@ type GetExpiredUpcomingEventsRow struct {
AwayKitImage pgtype.Text `json:"away_kit_image"` AwayKitImage pgtype.Text `json:"away_kit_image"`
LeagueID pgtype.Int4 `json:"league_id"` LeagueID pgtype.Int4 `json:"league_id"`
LeagueName pgtype.Text `json:"league_name"` LeagueName pgtype.Text `json:"league_name"`
LeagueCc pgtype.Text `json:"league_cc"`
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
Score pgtype.Text `json:"score"`
MatchMinute pgtype.Int4 `json:"match_minute"`
TimerStatus pgtype.Text `json:"timer_status"`
AddedTime pgtype.Int4 `json:"added_time"`
MatchPeriod pgtype.Int4 `json:"match_period"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
LeagueCc pgtype.Text `json:"league_cc"` Source pgtype.Text `json:"source"`
Flagged bool `json:"flagged"`
LeagueCc_2 pgtype.Text `json:"league_cc_2"`
} }
func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Text) ([]GetExpiredUpcomingEventsRow, error) { func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Text) ([]GetExpiredUpcomingEventsRow, error) {
@ -173,12 +135,19 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Te
&i.AwayKitImage, &i.AwayKitImage,
&i.LeagueID, &i.LeagueID,
&i.LeagueName, &i.LeagueName,
&i.LeagueCc,
&i.StartTime, &i.StartTime,
&i.Score,
&i.MatchMinute,
&i.TimerStatus,
&i.AddedTime,
&i.MatchPeriod,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
&i.LeagueCc, &i.Source,
&i.Flagged,
&i.LeagueCc_2,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -191,22 +160,7 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Te
} }
const GetPaginatedUpcomingEvents = `-- name: GetPaginatedUpcomingEvents :many const GetPaginatedUpcomingEvents = `-- name: GetPaginatedUpcomingEvents :many
SELECT events.id, SELECT events.id, events.sport_id, events.match_name, events.home_team, events.away_team, events.home_team_id, events.away_team_id, events.home_kit_image, events.away_kit_image, events.league_id, events.league_name, events.league_cc, events.start_time, events.score, events.match_minute, events.timer_status, events.added_time, events.match_period, events.is_live, events.status, events.fetched_at, events.source, events.flagged,
events.sport_id,
events.match_name,
events.home_team,
events.away_team,
events.home_team_id,
events.away_team_id,
events.home_kit_image,
events.away_kit_image,
events.league_id,
events.league_name,
events.start_time,
events.is_live,
events.status,
events.source,
events.fetched_at,
leagues.country_code as league_cc leagues.country_code as league_cc
FROM events FROM events
LEFT JOIN leagues ON leagues.id = league_id LEFT JOIN leagues ON leagues.id = league_id
@ -259,12 +213,19 @@ type GetPaginatedUpcomingEventsRow struct {
AwayKitImage pgtype.Text `json:"away_kit_image"` AwayKitImage pgtype.Text `json:"away_kit_image"`
LeagueID pgtype.Int4 `json:"league_id"` LeagueID pgtype.Int4 `json:"league_id"`
LeagueName pgtype.Text `json:"league_name"` LeagueName pgtype.Text `json:"league_name"`
LeagueCc pgtype.Text `json:"league_cc"`
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
Score pgtype.Text `json:"score"`
MatchMinute pgtype.Int4 `json:"match_minute"`
TimerStatus pgtype.Text `json:"timer_status"`
AddedTime pgtype.Int4 `json:"added_time"`
MatchPeriod pgtype.Int4 `json:"match_period"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
LeagueCc pgtype.Text `json:"league_cc"` Source pgtype.Text `json:"source"`
Flagged bool `json:"flagged"`
LeagueCc_2 pgtype.Text `json:"league_cc_2"`
} }
func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginatedUpcomingEventsParams) ([]GetPaginatedUpcomingEventsRow, error) { func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginatedUpcomingEventsParams) ([]GetPaginatedUpcomingEventsRow, error) {
@ -296,12 +257,19 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
&i.AwayKitImage, &i.AwayKitImage,
&i.LeagueID, &i.LeagueID,
&i.LeagueName, &i.LeagueName,
&i.LeagueCc,
&i.StartTime, &i.StartTime,
&i.Score,
&i.MatchMinute,
&i.TimerStatus,
&i.AddedTime,
&i.MatchPeriod,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
&i.LeagueCc, &i.Source,
&i.Flagged,
&i.LeagueCc_2,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -363,23 +331,7 @@ func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams)
} }
const GetUpcomingByID = `-- name: GetUpcomingByID :one const GetUpcomingByID = `-- name: GetUpcomingByID :one
SELECT id, SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, league_cc, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, flagged
sport_id,
match_name,
home_team,
away_team,
home_team_id,
away_team_id,
home_kit_image,
away_kit_image,
league_id,
league_name,
league_cc,
start_time,
is_live,
status,
source,
fetched_at
FROM events FROM events
WHERE id = $1 WHERE id = $1
AND is_live = false AND is_live = false
@ -387,29 +339,9 @@ WHERE id = $1
LIMIT 1 LIMIT 1
` `
type GetUpcomingByIDRow struct { func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (Event, error) {
ID string `json:"id"`
SportID pgtype.Int4 `json:"sport_id"`
MatchName pgtype.Text `json:"match_name"`
HomeTeam pgtype.Text `json:"home_team"`
AwayTeam pgtype.Text `json:"away_team"`
HomeTeamID pgtype.Int4 `json:"home_team_id"`
AwayTeamID pgtype.Int4 `json:"away_team_id"`
HomeKitImage pgtype.Text `json:"home_kit_image"`
AwayKitImage pgtype.Text `json:"away_kit_image"`
LeagueID pgtype.Int4 `json:"league_id"`
LeagueName pgtype.Text `json:"league_name"`
LeagueCc pgtype.Text `json:"league_cc"`
StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"`
}
func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingByIDRow, error) {
row := q.db.QueryRow(ctx, GetUpcomingByID, id) row := q.db.QueryRow(ctx, GetUpcomingByID, id)
var i GetUpcomingByIDRow var i Event
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.SportID, &i.SportID,
@ -424,10 +356,16 @@ func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingBy
&i.LeagueName, &i.LeagueName,
&i.LeagueCc, &i.LeagueCc,
&i.StartTime, &i.StartTime,
&i.Score,
&i.MatchMinute,
&i.TimerStatus,
&i.AddedTime,
&i.MatchPeriod,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
&i.Source,
&i.Flagged,
) )
return i, err return i, err
} }
@ -673,11 +611,26 @@ func (q *Queries) ListLiveEvents(ctx context.Context) ([]string, error) {
return items, nil return items, nil
} }
const UpdateFlagged = `-- name: UpdateFlagged :exec
UPDATE events
SET flagged = $1
WHERE id = $2
`
type UpdateFlaggedParams struct {
Flagged bool `json:"flagged"`
ID string `json:"id"`
}
func (q *Queries) UpdateFlagged(ctx context.Context, arg UpdateFlaggedParams) error {
_, err := q.db.Exec(ctx, UpdateFlagged, arg.Flagged, arg.ID)
return err
}
const UpdateMatchResult = `-- name: UpdateMatchResult :exec const UpdateMatchResult = `-- name: UpdateMatchResult :exec
UPDATE events UPDATE events
SET score = $1, SET score = $1,
status = $2, status = $2
fetched_at = NOW()
WHERE id = $3 WHERE id = $3
` `

View File

@ -10,7 +10,8 @@ import (
) )
const CountReportedIssues = `-- name: CountReportedIssues :one const CountReportedIssues = `-- name: CountReportedIssues :one
SELECT COUNT(*) FROM reported_issues SELECT COUNT(*)
FROM reported_issues
` `
func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) { func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) {
@ -20,12 +21,14 @@ func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) {
return count, err return count, err
} }
const CountReportedIssuesByCustomer = `-- name: CountReportedIssuesByCustomer :one const CountReportedIssuesByUser = `-- name: CountReportedIssuesByUser :one
SELECT COUNT(*) FROM reported_issues WHERE customer_id = $1 SELECT COUNT(*)
FROM reported_issues
WHERE user_id = $1
` `
func (q *Queries) CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error) { func (q *Queries) CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error) {
row := q.db.QueryRow(ctx, CountReportedIssuesByCustomer, customerID) row := q.db.QueryRow(ctx, CountReportedIssuesByUser, userID)
var count int64 var count int64
err := row.Scan(&count) err := row.Scan(&count)
return count, err return count, err
@ -33,15 +36,20 @@ func (q *Queries) CountReportedIssuesByCustomer(ctx context.Context, customerID
const CreateReportedIssue = `-- name: CreateReportedIssue :one const CreateReportedIssue = `-- name: CreateReportedIssue :one
INSERT INTO reported_issues ( INSERT INTO reported_issues (
customer_id, subject, description, issue_type, metadata user_id,
) VALUES ( user_role,
$1, $2, $3, $4, $5 subject,
) description,
RETURNING id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at issue_type,
metadata
)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
` `
type CreateReportedIssueParams struct { type CreateReportedIssueParams struct {
CustomerID int64 `json:"customer_id"` UserID int64 `json:"user_id"`
UserRole string `json:"user_role"`
Subject string `json:"subject"` Subject string `json:"subject"`
Description string `json:"description"` Description string `json:"description"`
IssueType string `json:"issue_type"` IssueType string `json:"issue_type"`
@ -50,7 +58,8 @@ type CreateReportedIssueParams struct {
func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIssueParams) (ReportedIssue, error) { func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIssueParams) (ReportedIssue, error) {
row := q.db.QueryRow(ctx, CreateReportedIssue, row := q.db.QueryRow(ctx, CreateReportedIssue,
arg.CustomerID, arg.UserID,
arg.UserRole,
arg.Subject, arg.Subject,
arg.Description, arg.Description,
arg.IssueType, arg.IssueType,
@ -59,7 +68,8 @@ func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIss
var i ReportedIssue var i ReportedIssue
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.CustomerID, &i.UserID,
&i.UserRole,
&i.Subject, &i.Subject,
&i.Description, &i.Description,
&i.IssueType, &i.IssueType,
@ -72,7 +82,8 @@ func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIss
} }
const DeleteReportedIssue = `-- name: DeleteReportedIssue :exec const DeleteReportedIssue = `-- name: DeleteReportedIssue :exec
DELETE FROM reported_issues WHERE id = $1 DELETE FROM reported_issues
WHERE id = $1
` `
func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error { func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error {
@ -81,7 +92,8 @@ func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error {
} }
const ListReportedIssues = `-- name: ListReportedIssues :many const ListReportedIssues = `-- name: ListReportedIssues :many
SELECT id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at FROM reported_issues SELECT id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
FROM reported_issues
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT $1 OFFSET $2 LIMIT $1 OFFSET $2
` `
@ -102,7 +114,8 @@ func (q *Queries) ListReportedIssues(ctx context.Context, arg ListReportedIssues
var i ReportedIssue var i ReportedIssue
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.CustomerID, &i.UserID,
&i.UserRole,
&i.Subject, &i.Subject,
&i.Description, &i.Description,
&i.IssueType, &i.IssueType,
@ -121,21 +134,22 @@ func (q *Queries) ListReportedIssues(ctx context.Context, arg ListReportedIssues
return items, nil return items, nil
} }
const ListReportedIssuesByCustomer = `-- name: ListReportedIssuesByCustomer :many const ListReportedIssuesByUser = `-- name: ListReportedIssuesByUser :many
SELECT id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at FROM reported_issues SELECT id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
WHERE customer_id = $1 FROM reported_issues
WHERE user_id = $1
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT $2 OFFSET $3 LIMIT $2 OFFSET $3
` `
type ListReportedIssuesByCustomerParams struct { type ListReportedIssuesByUserParams struct {
CustomerID int64 `json:"customer_id"` UserID int64 `json:"user_id"`
Limit int32 `json:"limit"` Limit int32 `json:"limit"`
Offset int32 `json:"offset"` Offset int32 `json:"offset"`
} }
func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListReportedIssuesByCustomerParams) ([]ReportedIssue, error) { func (q *Queries) ListReportedIssuesByUser(ctx context.Context, arg ListReportedIssuesByUserParams) ([]ReportedIssue, error) {
rows, err := q.db.Query(ctx, ListReportedIssuesByCustomer, arg.CustomerID, arg.Limit, arg.Offset) rows, err := q.db.Query(ctx, ListReportedIssuesByUser, arg.UserID, arg.Limit, arg.Offset)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -145,7 +159,8 @@ func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListRepo
var i ReportedIssue var i ReportedIssue
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.CustomerID, &i.UserID,
&i.UserRole,
&i.Subject, &i.Subject,
&i.Description, &i.Description,
&i.IssueType, &i.IssueType,
@ -166,7 +181,8 @@ func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListRepo
const UpdateReportedIssueStatus = `-- name: UpdateReportedIssueStatus :exec const UpdateReportedIssueStatus = `-- name: UpdateReportedIssueStatus :exec
UPDATE reported_issues UPDATE reported_issues
SET status = $2, updated_at = NOW() SET status = $2,
updated_at = NOW()
WHERE id = $1 WHERE id = $1
` `

View File

@ -78,18 +78,13 @@ type Bet struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Status int32 `json:"status"` Status int32 `json:"status"`
FullName string `json:"full_name"` UserID int64 `json:"user_id"`
PhoneNumber string `json:"phone_number"`
CompanyID pgtype.Int8 `json:"company_id"`
BranchID pgtype.Int8 `json:"branch_id"`
UserID pgtype.Int8 `json:"user_id"`
CashedOut bool `json:"cashed_out"`
CashoutID string `json:"cashout_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
IsShopBet bool `json:"is_shop_bet"` IsShopBet bool `json:"is_shop_bet"`
CashedOut bool `json:"cashed_out"`
OutcomesHash string `json:"outcomes_hash"` OutcomesHash string `json:"outcomes_hash"`
FastCode string `json:"fast_code"` FastCode string `json:"fast_code"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
type BetOutcome struct { type BetOutcome struct {
@ -115,18 +110,15 @@ type BetWithOutcome struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Status int32 `json:"status"` Status int32 `json:"status"`
FullName string `json:"full_name"` UserID int64 `json:"user_id"`
PhoneNumber string `json:"phone_number"`
CompanyID pgtype.Int8 `json:"company_id"`
BranchID pgtype.Int8 `json:"branch_id"`
UserID pgtype.Int8 `json:"user_id"`
CashedOut bool `json:"cashed_out"`
CashoutID string `json:"cashout_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
IsShopBet bool `json:"is_shop_bet"` IsShopBet bool `json:"is_shop_bet"`
CashedOut bool `json:"cashed_out"`
OutcomesHash string `json:"outcomes_hash"` OutcomesHash string `json:"outcomes_hash"`
FastCode string `json:"fast_code"` FastCode string `json:"fast_code"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
FullName interface{} `json:"full_name"`
PhoneNumber pgtype.Text `json:"phone_number"`
Outcomes []BetOutcome `json:"outcomes"` Outcomes []BetOutcome `json:"outcomes"`
} }
@ -252,6 +244,7 @@ type Event struct {
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
Source pgtype.Text `json:"source"` Source pgtype.Text `json:"source"`
Flagged bool `json:"flagged"`
} }
type ExchangeRate struct { type ExchangeRate struct {
@ -366,7 +359,8 @@ type RefreshToken struct {
type ReportedIssue struct { type ReportedIssue struct {
ID int64 `json:"id"` ID int64 `json:"id"`
CustomerID int64 `json:"customer_id"` UserID int64 `json:"user_id"`
UserRole string `json:"user_role"`
Subject string `json:"subject"` Subject string `json:"subject"`
Description string `json:"description"` Description string `json:"description"`
IssueType string `json:"issue_type"` IssueType string `json:"issue_type"`

View File

@ -12,18 +12,35 @@ import (
) )
const GetBranchWiseReport = `-- name: GetBranchWiseReport :many const GetBranchWiseReport = `-- name: GetBranchWiseReport :many
SELECT SELECT b.branch_id,
b.branch_id,
br.name AS branch_name, br.name AS branch_name,
br.company_id, br.company_id,
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(b.amount), 0) AS total_cash_made, COALESCE(SUM(b.amount), 0) AS total_cash_made,
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out, COALESCE(
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs SUM(
FROM bets b CASE
JOIN branches br ON b.branch_id = br.id WHEN b.cashed_out THEN b.amount
ELSE 0
END
),
0
) AS total_cash_out,
COALESCE(
SUM(
CASE
WHEN b.status = 5 THEN b.amount
ELSE 0
END
),
0
) AS total_cash_backs
FROM shop_bet_detail b
JOIN branches br ON b.branch_id = br.id
WHERE b.created_at BETWEEN $1 AND $2 WHERE b.created_at BETWEEN $1 AND $2
GROUP BY b.branch_id, br.name, br.company_id GROUP BY b.branch_id,
br.name,
br.company_id
` `
type GetBranchWiseReportParams struct { type GetBranchWiseReportParams struct {
@ -32,7 +49,7 @@ type GetBranchWiseReportParams struct {
} }
type GetBranchWiseReportRow struct { type GetBranchWiseReportRow struct {
BranchID pgtype.Int8 `json:"branch_id"` BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"` BranchName string `json:"branch_name"`
CompanyID int64 `json:"company_id"` CompanyID int64 `json:"company_id"`
TotalBets int64 `json:"total_bets"` TotalBets int64 `json:"total_bets"`
@ -70,17 +87,33 @@ func (q *Queries) GetBranchWiseReport(ctx context.Context, arg GetBranchWiseRepo
} }
const GetCompanyWiseReport = `-- name: GetCompanyWiseReport :many const GetCompanyWiseReport = `-- name: GetCompanyWiseReport :many
SELECT SELECT b.company_id,
b.company_id,
c.name AS company_name, c.name AS company_name,
COUNT(*) AS total_bets, COUNT(*) AS total_bets,
COALESCE(SUM(b.amount), 0) AS total_cash_made, COALESCE(SUM(b.amount), 0) AS total_cash_made,
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out, COALESCE(
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs SUM(
FROM bets b CASE
JOIN companies c ON b.company_id = c.id WHEN b.cashed_out THEN b.amount
ELSE 0
END
),
0
) AS total_cash_out,
COALESCE(
SUM(
CASE
WHEN b.status = 5 THEN b.amount
ELSE 0
END
),
0
) AS total_cash_backs
FROM shop_bet_detail b
JOIN companies c ON b.company_id = c.id
WHERE b.created_at BETWEEN $1 AND $2 WHERE b.created_at BETWEEN $1 AND $2
GROUP BY b.company_id, c.name GROUP BY b.company_id,
c.name
` `
type GetCompanyWiseReportParams struct { type GetCompanyWiseReportParams struct {
@ -89,7 +122,7 @@ type GetCompanyWiseReportParams struct {
} }
type GetCompanyWiseReportRow struct { type GetCompanyWiseReportRow struct {
CompanyID pgtype.Int8 `json:"company_id"` CompanyID int64 `json:"company_id"`
CompanyName string `json:"company_name"` CompanyName string `json:"company_name"`
TotalBets int64 `json:"total_bets"` TotalBets int64 `json:"total_bets"`
TotalCashMade interface{} `json:"total_cash_made"` TotalCashMade interface{} `json:"total_cash_made"`

View File

@ -38,29 +38,23 @@ type CreateBetOutcome struct {
Expires time.Time `json:"expires" example:"2025-04-08T12:00:00Z"` Expires time.Time `json:"expires" example:"2025-04-08T12:00:00Z"`
} }
// If it is a ShopBet then UserID will be the cashier // If it is a ShopBet then UserID and Fullname will be the cashier
// If it is a DigitalBet then UserID will be the user and the branchID will be 0 or nil // If it is a DigitalBet then UserID and Fullname will be the user
type Bet struct { type Bet struct {
ID int64 ID int64
Amount Currency Amount Currency
TotalOdds float32 TotalOdds float32
Status OutcomeStatus Status OutcomeStatus
FullName string UserID int64
PhoneNumber string
BranchID ValidInt64 // Can Be Nullable
CompanyID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool IsShopBet bool
CashedOut bool CashedOut bool
CashoutID string
FastCode string FastCode string
CreatedAt time.Time CreatedAt time.Time
} }
type BetFilter struct { type BetFilter struct {
BranchID ValidInt64 // Can Be Nullable UserID ValidInt64
CompanyID ValidInt64 // Can Be Nullable CashedOut ValidBool
UserID ValidInt64 // Can Be Nullable
IsShopBet ValidBool IsShopBet ValidBool
Query ValidString Query ValidString
CreatedBefore ValidTime CreatedBefore ValidTime
@ -74,12 +68,9 @@ type GetBet struct {
Status OutcomeStatus Status OutcomeStatus
FullName string FullName string
PhoneNumber string PhoneNumber string
BranchID ValidInt64 // Can Be Nullable UserID int64
CompanyID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool IsShopBet bool
CashedOut bool CashedOut bool
CashoutID string
Outcomes []BetOutcome Outcomes []BetOutcome
FastCode string FastCode string
CreatedAt time.Time CreatedAt time.Time
@ -89,13 +80,8 @@ type CreateBet struct {
Amount Currency Amount Currency
TotalOdds float32 TotalOdds float32
Status OutcomeStatus Status OutcomeStatus
FullName string UserID int64
PhoneNumber string
CompanyID ValidInt64 // Can Be Nullable
BranchID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool IsShopBet bool
CashoutID string
OutcomesHash string OutcomesHash string
FastCode string FastCode string
} }
@ -109,9 +95,6 @@ type CreateBetOutcomeReq struct {
type CreateBetReq struct { type CreateBetReq struct {
Outcomes []CreateBetOutcomeReq `json:"outcomes"` Outcomes []CreateBetOutcomeReq `json:"outcomes"`
Amount float32 `json:"amount" example:"100.0"` Amount float32 `json:"amount" example:"100.0"`
FullName string `json:"full_name" example:"John"`
PhoneNumber string `json:"phone_number" example:"1234567890"`
BranchID *int64 `json:"branch_id,omitempty" example:"1"`
} }
type RandomBetReq struct { type RandomBetReq struct {
@ -124,13 +107,9 @@ type CreateBetRes struct {
Amount float32 `json:"amount" example:"100.0"` Amount float32 `json:"amount" example:"100.0"`
TotalOdds float32 `json:"total_odds" example:"4.22"` TotalOdds float32 `json:"total_odds" example:"4.22"`
Status OutcomeStatus `json:"status" example:"1"` Status OutcomeStatus `json:"status" example:"1"`
FullName string `json:"full_name" example:"John"`
PhoneNumber string `json:"phone_number" example:"1234567890"`
BranchID int64 `json:"branch_id" example:"2"`
UserID int64 `json:"user_id" example:"2"` UserID int64 `json:"user_id" example:"2"`
IsShopBet bool `json:"is_shop_bet" example:"false"` IsShopBet bool `json:"is_shop_bet" example:"false"`
CreatedNumber int64 `json:"created_number" example:"2"` CreatedNumber int64 `json:"created_number" example:"2"`
CashedID string `json:"cashed_id" example:"21234"`
} }
type BetRes struct { type BetRes struct {
ID int64 `json:"id" example:"1"` ID int64 `json:"id" example:"1"`
@ -138,14 +117,12 @@ type BetRes struct {
Amount float32 `json:"amount" example:"100.0"` Amount float32 `json:"amount" example:"100.0"`
TotalOdds float32 `json:"total_odds" example:"4.22"` TotalOdds float32 `json:"total_odds" example:"4.22"`
Status OutcomeStatus `json:"status" example:"1"` Status OutcomeStatus `json:"status" example:"1"`
FullName string `json:"full_name" example:"John"` Fullname string `json:"full_name" example:"John Smith"`
PhoneNumber string `json:"phone_number" example:"1234567890"`
BranchID int64 `json:"branch_id" example:"2"`
UserID int64 `json:"user_id" example:"2"` UserID int64 `json:"user_id" example:"2"`
IsShopBet bool `json:"is_shop_bet" example:"false"` IsShopBet bool `json:"is_shop_bet" example:"false"`
CashedOut bool `json:"cashed_out" example:"false"` CashedOut bool `json:"cashed_out" example:"false"`
CashedID string `json:"cashed_id" example:"21234"`
CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"` CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"`
FastCode string `json:"fast_code"`
} }
func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes { func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes {
@ -154,12 +131,8 @@ func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes {
Amount: bet.Amount.Float32(), Amount: bet.Amount.Float32(),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: bet.Status, Status: bet.Status,
FullName: bet.FullName, UserID: bet.UserID,
PhoneNumber: bet.PhoneNumber,
BranchID: bet.BranchID.Value,
UserID: bet.UserID.Value,
CreatedNumber: createdNumber, CreatedNumber: createdNumber,
CashedID: bet.CashoutID,
} }
} }
@ -169,14 +142,12 @@ func ConvertBet(bet GetBet) BetRes {
Amount: bet.Amount.Float32(), Amount: bet.Amount.Float32(),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: bet.Status, Status: bet.Status,
FullName: bet.FullName, Fullname: bet.FullName,
PhoneNumber: bet.PhoneNumber, UserID: bet.UserID,
BranchID: bet.BranchID.Value,
UserID: bet.UserID.Value,
Outcomes: bet.Outcomes, Outcomes: bet.Outcomes,
IsShopBet: bet.IsShopBet, IsShopBet: bet.IsShopBet,
CashedOut: bet.CashedOut, CashedOut: bet.CashedOut,
CashedID: bet.CashoutID,
CreatedAt: bet.CreatedAt, CreatedAt: bet.CreatedAt,
FastCode: bet.FastCode,
} }
} }

View File

@ -101,6 +101,7 @@ type UpcomingEvent struct {
StartTime time.Time `json:"start_time"` // Converted from "time" field in UNIX format StartTime time.Time `json:"start_time"` // Converted from "time" field in UNIX format
Source string `json:"source"` // bet api provider (bet365, betfair) Source string `json:"source"` // bet api provider (bet365, betfair)
Status EventStatus `json:"status"` //Match Status for event Status EventStatus `json:"status"` //Match Status for event
Flagged bool `json:"flagged"` //Whether the event is flagged or not
} }
type MatchResult struct { type MatchResult struct {
EventID string EventID string

View File

@ -2,14 +2,51 @@ package domain
import "time" import "time"
type ReportedIssueType string
var (
ISSUE_TYPE_DEPOSIT ReportedIssueType = "deposit"
ISSUE_TYPE_WITHDRAWAL ReportedIssueType = "withdrawal"
ISSUE_TYPE_BET ReportedIssueType = "bet"
ISSUE_TYPE_CASHOUT ReportedIssueType = "cashout"
ISSUE_TYPE_ODDS ReportedIssueType = "odds"
ISSUE_TYPE_EVENTS ReportedIssueType = "events"
ISSUE_TYPE_BRANCH ReportedIssueType = "branch"
ISSUE_TYPE_USER ReportedIssueType = "branch"
ISSUE_TYPE_LOGIN ReportedIssueType = "login"
ISSUE_TYPE_REGISTER ReportedIssueType = "register"
ISSUE_TYPE_RESET_PASSWORD ReportedIssueType = "reset_password"
ISSUE_TYPE_WALLET ReportedIssueType = "wallet"
ISSUE_TYPE_VIRTUAL ReportedIssueType = "virtual games"
ISSUE_TYPE_OTHER ReportedIssueType = "other"
)
type ReportedIssueStatus string
var (
ISSUE_STATUS_PENDING ReportedIssueStatus = "pending"
ISSUE_STATUS_IN_PROGRESS ReportedIssueStatus = "in_progress"
ISSUE_STATUS_RESOLVED ReportedIssueStatus = "resolved"
ISSUE_STATUS_REJECTED ReportedIssueStatus = "rejected"
)
type ReportedIssue struct { type ReportedIssue struct {
ID int64 `json:"id"` ID int64 `json:"id"`
CustomerID int64 `json:"customer_id"` UserID int64 `json:"user_id"`
UserRole Role `json:"user_role"`
Subject string `json:"subject"` Subject string `json:"subject"`
Description string `json:"description"` Description string `json:"description"`
IssueType string `json:"issue_type"` IssueType ReportedIssueType `json:"issue_type"`
Status string `json:"status"` Status ReportedIssueStatus `json:"status"`
Metadata map[string]interface{} `json:"metadata,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
} }
type ReportedIssueReq struct {
ID int64 `json:"id"`
Subject string `json:"subject"`
Description string `json:"description"`
IssueType ReportedIssueType `json:"issue_type"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}

View File

@ -25,23 +25,10 @@ func convertDBBet(bet dbgen.Bet) domain.Bet {
Amount: domain.Currency(bet.Amount), Amount: domain.Currency(bet.Amount),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: domain.OutcomeStatus(bet.Status), Status: domain.OutcomeStatus(bet.Status),
FullName: bet.FullName, UserID: bet.UserID,
PhoneNumber: bet.PhoneNumber,
BranchID: domain.ValidInt64{
Value: bet.BranchID.Int64,
Valid: bet.BranchID.Valid,
},
CompanyID: domain.ValidInt64{
Value: bet.CompanyID.Int64,
Valid: bet.CompanyID.Valid,
},
UserID: domain.ValidInt64{
Value: bet.UserID.Int64,
Valid: bet.UserID.Valid,
},
IsShopBet: bet.IsShopBet, IsShopBet: bet.IsShopBet,
CashedOut: bet.CashedOut, CashedOut: bet.CashedOut,
CashoutID: bet.CashoutID, FastCode: bet.FastCode,
CreatedAt: bet.CreatedAt.Time, CreatedAt: bet.CreatedAt.Time,
} }
} }
@ -78,20 +65,13 @@ func convertDBBetWithOutcomes(bet dbgen.BetWithOutcome) domain.GetBet {
Amount: domain.Currency(bet.Amount), Amount: domain.Currency(bet.Amount),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: domain.OutcomeStatus(bet.Status), Status: domain.OutcomeStatus(bet.Status),
FullName: bet.FullName, FullName: bet.FullName.(string),
PhoneNumber: bet.PhoneNumber, PhoneNumber: bet.PhoneNumber.String,
BranchID: domain.ValidInt64{ UserID: bet.UserID,
Value: bet.BranchID.Int64,
Valid: bet.BranchID.Valid,
},
UserID: domain.ValidInt64{
Value: bet.UserID.Int64,
Valid: bet.UserID.Valid,
},
IsShopBet: bet.IsShopBet, IsShopBet: bet.IsShopBet,
CashedOut: bet.CashedOut, CashedOut: bet.CashedOut,
CashoutID: bet.CashoutID,
Outcomes: outcomes, Outcomes: outcomes,
FastCode: bet.FastCode,
CreatedAt: bet.CreatedAt.Time, CreatedAt: bet.CreatedAt.Time,
} }
} }
@ -122,19 +102,8 @@ func convertCreateBet(bet domain.CreateBet) dbgen.CreateBetParams {
Amount: int64(bet.Amount), Amount: int64(bet.Amount),
TotalOdds: bet.TotalOdds, TotalOdds: bet.TotalOdds,
Status: int32(bet.Status), Status: int32(bet.Status),
FullName: bet.FullName, UserID: bet.UserID,
PhoneNumber: bet.PhoneNumber,
BranchID: pgtype.Int8{
Int64: bet.BranchID.Value,
Valid: bet.BranchID.Valid,
},
UserID: pgtype.Int8{
Int64: bet.UserID.Value,
Valid: bet.UserID.Valid,
},
IsShopBet: bet.IsShopBet, IsShopBet: bet.IsShopBet,
CashoutID: bet.CashoutID,
OutcomesHash: bet.OutcomesHash, OutcomesHash: bet.OutcomesHash,
FastCode: bet.FastCode, FastCode: bet.FastCode,
} }
@ -184,33 +153,16 @@ func (s *Store) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
return convertDBBetWithOutcomes(bet), nil return convertDBBetWithOutcomes(bet), nil
} }
func (s *Store) GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error) {
bet, err := s.queries.GetBetByCashoutID(ctx, id)
if err != nil {
domain.MongoDBLogger.Error("failed to get bet by cashout ID",
zap.String("cashout_id", id),
zap.Error(err),
)
return domain.GetBet{}, err
}
return convertDBBetWithOutcomes(bet), nil
}
func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) { func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
bets, err := s.queries.GetAllBets(ctx, dbgen.GetAllBetsParams{ bets, err := s.queries.GetAllBets(ctx, dbgen.GetAllBetsParams{
BranchID: pgtype.Int8{
Int64: filter.BranchID.Value,
Valid: filter.BranchID.Valid,
},
CompanyID: pgtype.Int8{
Int64: filter.CompanyID.Value,
Valid: filter.CompanyID.Valid,
},
UserID: pgtype.Int8{ UserID: pgtype.Int8{
Int64: filter.UserID.Value, Int64: filter.UserID.Value,
Valid: filter.UserID.Valid, Valid: filter.UserID.Valid,
}, },
CashedOut: pgtype.Bool{
Bool: filter.CashedOut.Value,
Valid: filter.CashedOut.Valid,
},
IsShopBet: pgtype.Bool{ IsShopBet: pgtype.Bool{
Bool: filter.IsShopBet.Value, Bool: filter.IsShopBet.Value,
Valid: filter.IsShopBet.Valid, Valid: filter.IsShopBet.Valid,
@ -244,32 +196,8 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
return result, nil return result, nil
} }
func (s *Store) GetBetByBranchID(ctx context.Context, BranchID int64) ([]domain.GetBet, error) {
bets, err := s.queries.GetBetByBranchID(ctx, pgtype.Int8{
Int64: BranchID,
Valid: true,
})
if err != nil {
domain.MongoDBLogger.Error("failed to get bets by branch ID",
zap.Int64("branch_id", BranchID),
zap.Error(err),
)
return nil, err
}
var result []domain.GetBet = make([]domain.GetBet, 0, len(bets))
for _, bet := range bets {
result = append(result, convertDBBetWithOutcomes(bet))
}
return result, nil
}
func (s *Store) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) { func (s *Store) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) {
bets, err := s.queries.GetBetByUserID(ctx, pgtype.Int8{ bets, err := s.queries.GetBetByUserID(ctx, UserID)
Int64: UserID,
Valid: true,
})
if err != nil { if err != nil {
return nil, err return nil, err
@ -295,7 +223,7 @@ func (s *Store) GetBetByFastCode(ctx context.Context, fastcode string) (domain.G
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) { func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{ count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
UserID: pgtype.Int8{Int64: UserID, Valid: true}, UserID: UserID,
OutcomesHash: outcomesHash, OutcomesHash: outcomesHash,
}) })
@ -462,21 +390,21 @@ func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
argPos := 1 argPos := 1
// Add filters if provided // Add filters if provided
if filter.CompanyID.Valid { // if filter.CompanyID.Valid {
query += fmt.Sprintf(" WHERE company_id = $%d", argPos) // query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
args = append(args, filter.CompanyID.Value) // args = append(args, filter.CompanyID.Value)
argPos++ // argPos++
} // }
if filter.BranchID.Valid { // if filter.BranchID.Valid {
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string { // query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
if len(args) == 0 { // if len(args) == 0 {
return " WHERE " // return " WHERE "
} // }
return " AND " // return " AND "
}(), argPos) // }(), argPos)
args = append(args, filter.BranchID.Value) // args = append(args, filter.BranchID.Value)
argPos++ // argPos++
} // }
if filter.UserID.Valid { if filter.UserID.Valid {
query += fmt.Sprintf(" AND %suser_id = $%d", func() string { query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
if len(args) == 0 { if len(args) == 0 {

View File

@ -180,6 +180,7 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
StartTime: e.StartTime.Time.UTC(), StartTime: e.StartTime.Time.UTC(),
Source: e.Source.String, Source: e.Source.String,
Status: domain.EventStatus(e.Status.String), Status: domain.EventStatus(e.Status.String),
} }
} }
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{ totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
@ -268,6 +269,14 @@ func (s *Store) UpdateEventStatus(ctx context.Context, eventID string, status do
} }
func (s *Store) UpdateFlagged(ctx context.Context, eventID string, flagged bool) error {
return s.queries.UpdateFlagged(ctx, dbgen.UpdateFlaggedParams{
ID: eventID,
Flagged: flagged,
})
}
func (s *Store) DeleteEvent(ctx context.Context, eventID string) error { func (s *Store) DeleteEvent(ctx context.Context, eventID string) error {
err := s.queries.DeleteEvent(ctx, eventID) err := s.queries.DeleteEvent(ctx, eventID)
if err != nil { if err != nil {

View File

@ -9,9 +9,9 @@ import (
type ReportedIssueRepository interface { type ReportedIssueRepository interface {
CreateReportedIssue(ctx context.Context, arg dbgen.CreateReportedIssueParams) (dbgen.ReportedIssue, error) CreateReportedIssue(ctx context.Context, arg dbgen.CreateReportedIssueParams) (dbgen.ReportedIssue, error)
ListReportedIssues(ctx context.Context, limit, offset int32) ([]dbgen.ReportedIssue, error) ListReportedIssues(ctx context.Context, limit, offset int32) ([]dbgen.ReportedIssue, error)
ListReportedIssuesByCustomer(ctx context.Context, customerID int64, limit, offset int32) ([]dbgen.ReportedIssue, error) ListReportedIssuesByUser(ctx context.Context, userID int64, limit, offset int32) ([]dbgen.ReportedIssue, error)
CountReportedIssues(ctx context.Context) (int64, error) CountReportedIssues(ctx context.Context) (int64, error)
CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error) CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error)
UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error
DeleteReportedIssue(ctx context.Context, id int64) error DeleteReportedIssue(ctx context.Context, id int64) error
} }
@ -36,21 +36,21 @@ func (s *ReportedIssueRepo) ListReportedIssues(ctx context.Context, limit, offse
return s.store.queries.ListReportedIssues(ctx, params) return s.store.queries.ListReportedIssues(ctx, params)
} }
func (s *ReportedIssueRepo) ListReportedIssuesByCustomer(ctx context.Context, customerID int64, limit, offset int32) ([]dbgen.ReportedIssue, error) { func (s *ReportedIssueRepo) ListReportedIssuesByUser(ctx context.Context, userID int64, limit, offset int32) ([]dbgen.ReportedIssue, error) {
params := dbgen.ListReportedIssuesByCustomerParams{ params := dbgen.ListReportedIssuesByUserParams{
CustomerID: customerID, UserID: userID,
Limit: limit, Limit: limit,
Offset: offset, Offset: offset,
} }
return s.store.queries.ListReportedIssuesByCustomer(ctx, params) return s.store.queries.ListReportedIssuesByUser(ctx, params)
} }
func (s *ReportedIssueRepo) CountReportedIssues(ctx context.Context) (int64, error) { func (s *ReportedIssueRepo) CountReportedIssues(ctx context.Context) (int64, error) {
return s.store.queries.CountReportedIssues(ctx) return s.store.queries.CountReportedIssues(ctx)
} }
func (s *ReportedIssueRepo) CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error) { func (s *ReportedIssueRepo) CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error) {
return s.store.queries.CountReportedIssuesByCustomer(ctx, customerID) return s.store.queries.CountReportedIssuesByUser(ctx, userID)
} }
func (s *ReportedIssueRepo) UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error { func (s *ReportedIssueRepo) UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error {

View File

@ -20,7 +20,9 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers" "github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -36,6 +38,9 @@ var (
ErrBranchIDRequired = errors.New("Branch ID required for this role") ErrBranchIDRequired = errors.New("Branch ID required for this role")
ErrOutcomeLimit = errors.New("Too many outcomes on a single bet") ErrOutcomeLimit = errors.New("Too many outcomes on a single bet")
ErrTotalBalanceNotEnough = errors.New("Total Wallet balance is insufficient to create bet") ErrTotalBalanceNotEnough = errors.New("Total Wallet balance is insufficient to create bet")
ErrInvalidAmount = errors.New("Invalid amount")
ErrBetAmountTooHigh = errors.New("Cannot create a bet with an amount above limit")
) )
type Service struct { type Service struct {
@ -44,6 +49,8 @@ type Service struct {
prematchSvc odds.ServiceImpl prematchSvc odds.ServiceImpl
walletSvc wallet.Service walletSvc wallet.Service
branchSvc branch.Service branchSvc branch.Service
settingSvc settings.Service
notificationSvc *notificationservice.Service
logger *slog.Logger logger *slog.Logger
mongoLogger *zap.Logger mongoLogger *zap.Logger
} }
@ -54,6 +61,8 @@ func NewService(
prematchSvc odds.ServiceImpl, prematchSvc odds.ServiceImpl,
walletSvc wallet.Service, walletSvc wallet.Service,
branchSvc branch.Service, branchSvc branch.Service,
settingSvc settings.Service,
notificationSvc *notificationservice.Service,
logger *slog.Logger, logger *slog.Logger,
mongoLogger *zap.Logger, mongoLogger *zap.Logger,
) *Service { ) *Service {
@ -63,6 +72,8 @@ func NewService(
prematchSvc: prematchSvc, prematchSvc: prematchSvc,
walletSvc: walletSvc, walletSvc: walletSvc,
branchSvc: branchSvc, branchSvc: branchSvc,
settingSvc: settingSvc,
notificationSvc: notificationSvc,
logger: logger, logger: logger,
mongoLogger: mongoLogger, mongoLogger: mongoLogger,
} }
@ -196,7 +207,17 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
} }
func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID int64, role domain.Role) (domain.CreateBetRes, error) { func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID int64, role domain.Role) (domain.CreateBetRes, error) {
if len(req.Outcomes) > 30 { settingsList, err := s.settingSvc.GetSettingList(ctx)
if req.Amount < 1 {
return domain.CreateBetRes{}, ErrInvalidAmount
}
if req.Amount > settingsList.BetAmountLimit.Float32() {
return domain.CreateBetRes{}, ErrInvalidAmount
}
if len(req.Outcomes) > int(settingsList.MaxNumberOfOutcomes) {
s.mongoLogger.Error("too many outcomes", s.mongoLogger.Error("too many outcomes",
zap.Int("count", len(req.Outcomes)), zap.Int("count", len(req.Outcomes)),
zap.Int64("user_id", userID), zap.Int64("user_id", userID),
@ -237,7 +258,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
return domain.CreateBetRes{}, err return domain.CreateBetRes{}, err
} }
if count >= 2 { if count >= 2 {
return domain.CreateBetRes{}, fmt.Errorf("bet already pleaced twice") return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice")
} }
cashoutID, err := s.GenerateCashoutID() cashoutID, err := s.GenerateCashoutID()

View File

@ -16,4 +16,5 @@ type Service interface {
// GetAndStoreMatchResult(ctx context.Context, eventID string) error // GetAndStoreMatchResult(ctx context.Context, eventID string) error
UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error
UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error
UpdateFlagged(ctx context.Context, eventID string, flagged bool) error
} }

View File

@ -369,6 +369,10 @@ func (s *service) UpdateEventStatus(ctx context.Context, eventID string, status
return s.store.UpdateEventStatus(ctx, eventID, status) return s.store.UpdateEventStatus(ctx, eventID, status)
} }
func (s *service) UpdateFlagged(ctx context.Context, eventID string, flagged bool) error {
return s.store.UpdateFlagged(ctx, eventID, flagged)
}
// func (s *service) GetAndStoreMatchResult(ctx context.Context, eventID string) error { // func (s *service) GetAndStoreMatchResult(ctx context.Context, eventID string) error {
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.token, eventID) // url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.token, eventID)

View File

@ -17,15 +17,19 @@ func New(repo repository.ReportedIssueRepository) *Service {
return &Service{repo: repo} return &Service{repo: repo}
} }
func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.ReportedIssue) (domain.ReportedIssue, error) { func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.ReportedIssueReq, userID int64, role domain.Role) (domain.ReportedIssue, error) {
// metadata, err := json.Marshal(issue.Metadata)
// if err != nil {
// return domain.ReportedIssue{}, err
// }
params := dbgen.CreateReportedIssueParams{ params := dbgen.CreateReportedIssueParams{
// Map fields from domain.ReportedIssue to dbgen.CreateReportedIssueParams here. UserID: userID,
// Example: UserRole: string(role),
// Title: issue.Title, Subject: issue.Subject,
// Description: issue.Description, Description: issue.Description,
// CustomerID: issue.CustomerID, IssueType: string(issue.IssueType),
// Status: issue.Status, // Metadata: metadata,
// Add other fields as necessary.
} }
dbIssue, err := s.repo.CreateReportedIssue(ctx, params) dbIssue, err := s.repo.CreateReportedIssue(ctx, params)
if err != nil { if err != nil {
@ -36,17 +40,20 @@ func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.Reported
ID: dbIssue.ID, ID: dbIssue.ID,
Subject: dbIssue.Subject, Subject: dbIssue.Subject,
Description: dbIssue.Description, Description: dbIssue.Description,
CustomerID: dbIssue.CustomerID, UserID: dbIssue.UserID,
Status: dbIssue.Status, UserRole: domain.Role(dbIssue.UserRole),
Status: domain.ReportedIssueStatus(dbIssue.Status),
IssueType: domain.ReportedIssueType(dbIssue.IssueType),
CreatedAt: dbIssue.CreatedAt.Time, CreatedAt: dbIssue.CreatedAt.Time,
UpdatedAt: dbIssue.UpdatedAt.Time, UpdatedAt: dbIssue.UpdatedAt.Time,
// Add other fields as necessary // Add other fields as necessary
} }
return reportedIssue, nil return reportedIssue, nil
} }
func (s *Service) GetIssuesForCustomer(ctx context.Context, customerID int64, limit, offset int) ([]domain.ReportedIssue, error) { func (s *Service) GetIssuesForUser(ctx context.Context, userID int64, limit, offset int) ([]domain.ReportedIssue, error) {
dbIssues, err := s.repo.ListReportedIssuesByCustomer(ctx, customerID, int32(limit), int32(offset)) dbIssues, err := s.repo.ListReportedIssuesByUser(ctx, userID, int32(limit), int32(offset))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -56,8 +63,10 @@ func (s *Service) GetIssuesForCustomer(ctx context.Context, customerID int64, li
ID: dbIssue.ID, ID: dbIssue.ID,
Subject: dbIssue.Subject, Subject: dbIssue.Subject,
Description: dbIssue.Description, Description: dbIssue.Description,
CustomerID: dbIssue.CustomerID, UserID: dbIssue.UserID,
Status: dbIssue.Status, UserRole: domain.Role(dbIssue.UserRole),
Status: domain.ReportedIssueStatus(dbIssue.Status),
IssueType: domain.ReportedIssueType(dbIssue.IssueType),
CreatedAt: dbIssue.CreatedAt.Time, CreatedAt: dbIssue.CreatedAt.Time,
UpdatedAt: dbIssue.UpdatedAt.Time, UpdatedAt: dbIssue.UpdatedAt.Time,
// Add other fields as necessary // Add other fields as necessary

View File

@ -25,7 +25,7 @@ var (
ErrTicketAmountTooHigh = errors.New("Cannot create a ticket with an amount above limit") ErrTicketAmountTooHigh = errors.New("Cannot create a ticket with an amount above limit")
ErrTicketLimitForSingleUser = errors.New("Number of Ticket Limit reached") ErrTicketLimitForSingleUser = errors.New("Number of Ticket Limit reached")
ErrTicketWinningTooHigh = errors.New("Total Winnings over set limit") ErrTicketWinningTooHigh = errors.New("Total Winnings over set limit")
ErrInvalidAmount = errors.New("Invalid amount")
ErrRawOddInvalid = errors.New("Prematch Raw Odd is Invalid") ErrRawOddInvalid = errors.New("Prematch Raw Odd is Invalid")
) )
@ -167,6 +167,11 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
} }
if req.Amount < 1 {
return domain.Ticket{}, 0, ErrInvalidAmount
}
// Check to see if the amount is above a set limit // Check to see if the amount is above a set limit
if req.Amount > settingsList.BetAmountLimit.Float32() { if req.Amount > settingsList.BetAmountLimit.Float32() {
return domain.Ticket{}, 0, ErrTicketAmountTooHigh return domain.Ticket{}, 0, ErrTicketAmountTooHigh
@ -183,7 +188,6 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
// Check to see how many tickets a single anonymous user has created // Check to see how many tickets a single anonymous user has created
if count > settingsList.DailyTicketPerIP { if count > settingsList.DailyTicketPerIP {
return domain.Ticket{}, 0, ErrTicketLimitForSingleUser return domain.Ticket{}, 0, ErrTicketLimitForSingleUser
} }

View File

@ -23,22 +23,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
spec string spec string
task func() task func()
}{ }{
{ // {
spec: "0 0 * * * *", // Every 1 hour // spec: "0 0 * * * *", // Every 1 hour
task: func() { // task: func() {
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil { // if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
log.Printf("FetchUpcomingEvents error: %v", err) // log.Printf("FetchUpcomingEvents error: %v", err)
} // }
}, // },
}, // },
{ // {
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events) // spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
task: func() { // task: func() {
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { // if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
log.Printf("FetchNonLiveOdds error: %v", err) // log.Printf("FetchNonLiveOdds error: %v", err)
} // }
}, // },
}, // },
{ {
spec: "0 */5 * * * *", // Every 5 Minutes spec: "0 */5 * * * *", // Every 5 Minutes
task: func() { task: func() {

View File

@ -10,61 +10,6 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
// GetALLPrematchOdds
// @Summary Retrieve all prematch odds
// @Description Retrieve all prematch odds from the database
// @Tags prematch
// @Accept json
// @Produce json
// @Success 200 {array} domain.Odd
// @Failure 500 {object} response.APIResponse
// @Router /odds [get]
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
}
// GetRawOddsByMarketID
// @Summary Retrieve raw odds by Market ID
// @Description Retrieve raw odds records using a Market ID
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming ID"
// @Param market_id path string true "Market ID"
// @Success 200 {array} domain.RawOddsByMarketID
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id}/market/{market_id} [get]
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
marketID := c.Params("market_id")
upcomingID := c.Params("upcoming_id")
if marketID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
}
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil {
// fmt.Printf("Failed to fetch raw odds: %v market_id:%v upcomingID:%v\n", err, marketID, upcomingID)
h.logger.Error("Failed to get raw odds by market ID", "marketID", marketID, "upcomingID", upcomingID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
}
// @Summary Retrieve all upcoming events // @Summary Retrieve all upcoming events
// @Description Retrieve all upcoming events from the database // @Description Retrieve all upcoming events from the database
// @Tags prematch // @Tags prematch
@ -151,6 +96,10 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
Value: countryCodeQuery, Value: countryCodeQuery,
Valid: countryCodeQuery != "", Valid: countryCodeQuery != "",
} }
flaggedQuery := c.Query("flagged")
if flaggedQuery != "" &&
events, total, err := h.eventSvc.GetPaginatedUpcomingEvents( events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(
c.Context(), domain.EventFilter{ c.Context(), domain.EventFilter{
SportID: sportID, SportID: sportID,
@ -257,44 +206,6 @@ func (h *Handler) GetUpcomingEventByID(c *fiber.Ctx) error {
} }
// @Summary Retrieve prematch odds by upcoming ID (FI)
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming Event ID (FI)"
// @Param limit query int false "Number of results to return (default: 10)"
// @Param offset query int false "Number of results to skip (default: 0)"
// @Success 200 {array} domain.Odd
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id} [get]
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
upcomingID := c.Params("upcoming_id")
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
if err != nil || limit <= 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
}
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
if err != nil || offset < 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
}
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
}
type UpdateEventStatusReq struct { type UpdateEventStatusReq struct {
} }
@ -320,3 +231,45 @@ func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil) return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
} }
type UpdateEventFlaggedReq struct {
Flagged bool `json:"flagged" example:"true"`
}
// UpdateEventFlagged godoc
// @Summary update the event flagged
// @Description Update the event flagged
// @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 /events/{id}/flag [put]
func (h *Handler) UpdateEventFlagged(c *fiber.Ctx) error {
eventID := c.Params("id")
var req UpdateEventFlaggedReq
if err := c.BodyParser(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, 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)
}
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
err := h.eventSvc.UpdateFlagged(c.Context(), eventID, req.Flagged)
if err != nil {
h.logger.Error("Failed to update event flagged", "eventID", eventID, "error", err)
}
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
}

View File

@ -19,12 +19,15 @@ import (
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/issues [post] // @Router /api/v1/issues [post]
func (h *Handler) CreateIssue(c *fiber.Ctx) error { func (h *Handler) CreateIssue(c *fiber.Ctx) error {
var req domain.ReportedIssue role := c.Locals("role").(domain.Role)
userID := c.Locals("user_id").(int64)
var req domain.ReportedIssueReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
} }
created, err := h.issueReportingSvc.CreateReportedIssue(c.Context(), req) created, err := h.issueReportingSvc.CreateReportedIssue(c.Context(), req, userID, role)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error()) return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} }
@ -32,27 +35,27 @@ func (h *Handler) CreateIssue(c *fiber.Ctx) error {
return c.Status(fiber.StatusCreated).JSON(created) return c.Status(fiber.StatusCreated).JSON(created)
} }
// GetCustomerIssues godoc // GetUserIssues godoc
// @Summary Get reported issues by a customer // @Summary Get reported issues by a user
// @Description Returns all issues reported by a specific customer // @Description Returns all issues reported by a specific user
// @Tags Issues // @Tags Issues
// @Produce json // @Produce json
// @Param customer_id path int true "Customer ID" // @Param user_id path int true "User ID"
// @Param limit query int false "Limit" // @Param limit query int false "Limit"
// @Param offset query int false "Offset" // @Param offset query int false "Offset"
// @Success 200 {array} domain.ReportedIssue // @Success 200 {array} domain.ReportedIssue
// @Failure 400 {object} domain.ErrorResponse // @Failure 400 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/issues/customer/{customer_id} [get] // @Router /api/v1/issues/user/{user_id} [get]
func (h *Handler) GetCustomerIssues(c *fiber.Ctx) error { func (h *Handler) GetUserIssues(c *fiber.Ctx) error {
customerID, err := strconv.ParseInt(c.Params("customer_id"), 10, 64) userID, err := strconv.ParseInt(c.Params("user_id"), 10, 64)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid customer ID") return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
} }
limit, offset := getPaginationParams(c) limit, offset := getPaginationParams(c)
issues, err := h.issueReportingSvc.GetIssuesForCustomer(c.Context(), customerID, limit, offset) issues, err := h.issueReportingSvc.GetIssuesForUser(c.Context(), userID, limit, offset)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error()) return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} }

View File

@ -0,0 +1,102 @@
package handlers
import (
"strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
)
// GetALLPrematchOdds
// @Summary Retrieve all prematch odds
// @Description Retrieve all prematch odds from the database
// @Tags prematch
// @Accept json
// @Produce json
// @Success 200 {array} domain.Odd
// @Failure 500 {object} response.APIResponse
// @Router /odds [get]
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
}
// GetRawOddsByMarketID
// @Summary Retrieve raw odds by Market ID
// @Description Retrieve raw odds records using a Market ID
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming ID"
// @Param market_id path string true "Market ID"
// @Success 200 {array} domain.RawOddsByMarketID
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id}/market/{market_id} [get]
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
marketID := c.Params("market_id")
upcomingID := c.Params("upcoming_id")
if marketID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
}
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil {
// fmt.Printf("Failed to fetch raw odds: %v market_id:%v upcomingID:%v\n", err, marketID, upcomingID)
h.logger.Error("Failed to get raw odds by market ID", "marketID", marketID, "upcomingID", upcomingID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
}
// @Summary Retrieve prematch odds by upcoming ID (FI)
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming Event ID (FI)"
// @Param limit query int false "Number of results to return (default: 10)"
// @Param offset query int false "Number of results to skip (default: 0)"
// @Success 200 {array} domain.Odd
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id} [get]
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
upcomingID := c.Params("upcoming_id")
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
if err != nil || limit <= 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
}
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
if err != nil || offset < 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
}
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
}

View File

@ -61,6 +61,12 @@ func (a *App) initAppRoutes() {
}) })
}) })
group.Get("/", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"message": "FortuneBet API V1 pre-alpha",
"version": "1.0dev9",
})
})
// Auth Routes // Auth Routes
a.fiber.Post("/auth/login", h.LoginCustomer) a.fiber.Post("/auth/login", h.LoginCustomer)
a.fiber.Post("/auth/refresh", h.RefreshToken) a.fiber.Post("/auth/refresh", h.RefreshToken)
@ -146,6 +152,7 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/events/:id", h.GetUpcomingEventByID) a.fiber.Get("/events/:id", h.GetUpcomingEventByID)
a.fiber.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved) a.fiber.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
a.fiber.Get("/top-leagues", h.GetTopLeagues) a.fiber.Get("/top-leagues", h.GetTopLeagues)
a.fiber.Get("/events/:id/flag", h.UpdateEventFlagged)
// Leagues // Leagues
a.fiber.Get("/leagues", h.GetAllLeagues) a.fiber.Get("/leagues", h.GetAllLeagues)
@ -315,8 +322,8 @@ func (a *App) initAppRoutes() {
group.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites) group.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
//Issue Reporting Routes //Issue Reporting Routes
group.Post("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateIssue) group.Post("/issues", a.authMiddleware, h.CreateIssue) //anyone who has logged can report a
group.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetCustomerIssues) group.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
group.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues) group.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
group.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus) group.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
group.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue) group.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)

View File

@ -47,6 +47,7 @@ postgres:
backup: backup:
@mkdir -p backup @mkdir -p backup
@docker exec -t fortunebet-backend-postgres-1 pg_dumpall -c -U root | gzip > backup/dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.gz @docker exec -t fortunebet-backend-postgres-1 pg_dumpall -c -U root | gzip > backup/dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.gz
restore: restore:
@echo "Restoring latest backup..." @echo "Restoring latest backup..."
gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh