virtual_game_providers based SQL queries primary ID data type mismatch fix
This commit is contained in:
parent
168fcdf278
commit
13c470079c
41
cmd/main.go
41
cmd/main.go
|
|
@ -49,7 +49,6 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||||
|
|
@ -286,23 +285,23 @@ func main() {
|
||||||
*userSvc,
|
*userSvc,
|
||||||
)
|
)
|
||||||
|
|
||||||
reportSvc := report.NewService(
|
// reportSvc := report.NewService(
|
||||||
repository.NewReportStore(store),
|
// repository.NewVirtualGameReportStore(store),
|
||||||
repository.NewBetStore(store),
|
// repository.NewBetStore(store),
|
||||||
repository.NewWalletStore(store),
|
// repository.NewWalletStore(store),
|
||||||
repository.NewTransactionStore(store),
|
// repository.NewTransactionStore(store),
|
||||||
repository.NewBranchStore(store),
|
// repository.NewBranchStore(store),
|
||||||
repository.NewUserStore(store),
|
// repository.NewUserStore(store),
|
||||||
repository.NewOldRepositoryStore(store),
|
// repository.NewOldRepositoryStore(store),
|
||||||
repository.NewCompanyStore(store),
|
// repository.NewCompanyStore(store),
|
||||||
repository.NewVirtualGameRepository(store),
|
// repository.NewVirtualGameRepository(store),
|
||||||
repository.NewNotificationStore(store),
|
// repository.NewNotificationStore(store),
|
||||||
notificationSvc,
|
// notificationSvc,
|
||||||
statSvc,
|
// statSvc,
|
||||||
logger,
|
// logger,
|
||||||
domain.MongoDBLogger,
|
// domain.MongoDBLogger,
|
||||||
cfg,
|
// cfg,
|
||||||
)
|
// )
|
||||||
|
|
||||||
enePulseSvc := enetpulse.New(
|
enePulseSvc := enetpulse.New(
|
||||||
*cfg,
|
*cfg,
|
||||||
|
|
@ -310,7 +309,7 @@ func main() {
|
||||||
)
|
)
|
||||||
|
|
||||||
go httpserver.StartEnetPulseCron(enePulseSvc, domain.MongoDBLogger)
|
go httpserver.StartEnetPulseCron(enePulseSvc, domain.MongoDBLogger)
|
||||||
go httpserver.SetupReportandVirtualGameCronJobs(context.Background(), reportSvc, orchestrationSvc, "C:/Users/User/Desktop")
|
// go httpserver.SetupReportandVirtualGameCronJobs(context.Background(), reportSvc, orchestrationSvc, "C:/Users/User/Desktop")
|
||||||
go httpserver.ProcessBetCashback(context.TODO(), betSvc)
|
go httpserver.ProcessBetCashback(context.TODO(), betSvc)
|
||||||
|
|
||||||
bankRepository := repository.NewBankRepository(store)
|
bankRepository := repository.NewBankRepository(store)
|
||||||
|
|
@ -363,7 +362,7 @@ func main() {
|
||||||
httpserver.StartBetAPIDataFetchingCrons(eventSvc, *oddsSvc, resultSvc, domain.MongoDBLogger)
|
httpserver.StartBetAPIDataFetchingCrons(eventSvc, *oddsSvc, resultSvc, domain.MongoDBLogger)
|
||||||
httpserver.StartCleanupCrons(*ticketSvc, notificationSvc, domain.MongoDBLogger)
|
httpserver.StartCleanupCrons(*ticketSvc, notificationSvc, domain.MongoDBLogger)
|
||||||
httpserver.StartStatCrons(statSvc, domain.MongoDBLogger)
|
httpserver.StartStatCrons(statSvc, domain.MongoDBLogger)
|
||||||
httpserver.StartReportCrons(reportSvc, domain.MongoDBLogger)
|
// httpserver.StartReportCrons(reportSvc, domain.MongoDBLogger)
|
||||||
|
|
||||||
issueReportingRepo := repository.NewReportedIssueRepository(store)
|
issueReportingRepo := repository.NewReportedIssueRepository(store)
|
||||||
|
|
||||||
|
|
@ -405,7 +404,7 @@ func main() {
|
||||||
userSvc,
|
userSvc,
|
||||||
ticketSvc,
|
ticketSvc,
|
||||||
betSvc,
|
betSvc,
|
||||||
reportSvc, // Make sure httpserver.NewApp accepts this parameter
|
// reportSvc, // Make sure httpserver.NewApp accepts this parameter
|
||||||
chapaSvc,
|
chapaSvc,
|
||||||
walletSvc,
|
walletSvc,
|
||||||
transactionSvc,
|
transactionSvc,
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS virtual_game_providers (
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS virtual_game_provider_reports (
|
CREATE TABLE IF NOT EXISTS virtual_game_provider_reports (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(provider_id) ON DELETE CASCADE,
|
provider_id BIGINT NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
||||||
report_date DATE NOT NULL,
|
report_date DATE NOT NULL,
|
||||||
total_games_played BIGINT DEFAULT 0,
|
total_games_played BIGINT DEFAULT 0,
|
||||||
total_bets NUMERIC(18,2) DEFAULT 0,
|
total_bets NUMERIC(18,2) DEFAULT 0,
|
||||||
|
|
@ -55,7 +55,7 @@ ON virtual_game_provider_reports (provider_id, report_date, report_type);
|
||||||
CREATE TABLE IF NOT EXISTS virtual_games (
|
CREATE TABLE IF NOT EXISTS virtual_games (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
game_id VARCHAR(150) UNIQUE NOT NULL,
|
game_id VARCHAR(150) UNIQUE NOT NULL,
|
||||||
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(provider_id) ON DELETE CASCADE,
|
provider_id BIGINT NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
category VARCHAR(100),
|
category VARCHAR(100),
|
||||||
device_type VARCHAR(100),
|
device_type VARCHAR(100),
|
||||||
|
|
@ -75,7 +75,7 @@ CREATE TABLE IF NOT EXISTS virtual_game_favourites (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
game_id BIGINT NOT NULL REFERENCES virtual_games(id) ON DELETE CASCADE,
|
game_id BIGINT NOT NULL REFERENCES virtual_games(id) ON DELETE CASCADE,
|
||||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
provider_id BIGINT NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
UNIQUE (game_id, user_id)
|
UNIQUE (game_id, user_id)
|
||||||
);
|
);
|
||||||
|
|
@ -83,7 +83,7 @@ CREATE TABLE IF NOT EXISTS virtual_game_favourites (
|
||||||
CREATE TABLE IF NOT EXISTS virtual_game_reports (
|
CREATE TABLE IF NOT EXISTS virtual_game_reports (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
game_id VARCHAR(150) NOT NULL REFERENCES virtual_games(game_id) ON DELETE CASCADE,
|
game_id VARCHAR(150) NOT NULL REFERENCES virtual_games(game_id) ON DELETE CASCADE,
|
||||||
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(provider_id) ON DELETE CASCADE,
|
provider_id BIGINT NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
||||||
report_date DATE NOT NULL,
|
report_date DATE NOT NULL,
|
||||||
total_rounds BIGINT DEFAULT 0,
|
total_rounds BIGINT DEFAULT 0,
|
||||||
total_bets NUMERIC(18,2) DEFAULT 0,
|
total_bets NUMERIC(18,2) DEFAULT 0,
|
||||||
|
|
|
||||||
4
db/migrations/00009_virtual_reports.down.sql
Normal file
4
db/migrations/00009_virtual_reports.down.sql
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
DROP TABLE IF EXISTS virtual_game_financial_reports;
|
||||||
|
DROP TABLE IF EXISTS virtual_game_company_reports;
|
||||||
|
DROP TABLE IF EXISTS virtual_game_player_cashflow_reports;
|
||||||
|
DROP TABLE IF EXISTS virtual_game_player_session_reports;
|
||||||
73
db/migrations/00009_virtual_reports.up.sql
Normal file
73
db/migrations/00009_virtual_reports.up.sql
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS virtual_game_financial_reports (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
game_id VARCHAR(150) NOT NULL REFERENCES virtual_games(game_id) ON DELETE CASCADE,
|
||||||
|
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(provider_id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
report_date DATE NOT NULL,
|
||||||
|
report_type VARCHAR(50) NOT NULL DEFAULT 'daily',
|
||||||
|
|
||||||
|
total_bets NUMERIC(18,2) DEFAULT 0,
|
||||||
|
total_wins NUMERIC(18,2) DEFAULT 0,
|
||||||
|
|
||||||
|
ggr NUMERIC(18,2) GENERATED ALWAYS AS (total_bets - total_wins) STORED,
|
||||||
|
rtp NUMERIC(5,2) GENERATED ALWAYS AS (
|
||||||
|
CASE WHEN total_bets > 0 THEN (total_wins / total_bets) * 100 ELSE 0 END
|
||||||
|
) STORED,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS virtual_game_company_reports (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
|
||||||
|
company_id BIGINT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
||||||
|
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(provider_id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
report_date DATE NOT NULL,
|
||||||
|
report_type VARCHAR(50) NOT NULL DEFAULT 'daily',
|
||||||
|
|
||||||
|
total_bet_amount NUMERIC(18,2) DEFAULT 0,
|
||||||
|
total_win_amount NUMERIC(18,2) DEFAULT 0,
|
||||||
|
|
||||||
|
net_profit NUMERIC(18,2) GENERATED ALWAYS AS (total_bet_amount - total_win_amount) STORED,
|
||||||
|
profit_margin NUMERIC(6,3) GENERATED ALWAYS AS (
|
||||||
|
CASE WHEN total_bet_amount > 0 THEN (total_bet_amount - total_win_amount) / total_bet_amount ELSE 0 END
|
||||||
|
) STORED,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS virtual_game_player_activity_reports (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
|
||||||
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Reporting scope
|
||||||
|
report_date DATE NOT NULL,
|
||||||
|
report_type VARCHAR(50) NOT NULL DEFAULT 'daily',
|
||||||
|
|
||||||
|
-- Cashflow information
|
||||||
|
total_deposits NUMERIC(18,2) DEFAULT 0,
|
||||||
|
total_withdrawals NUMERIC(18,2) DEFAULT 0,
|
||||||
|
net_contribution NUMERIC(18,2) GENERATED ALWAYS AS (
|
||||||
|
total_deposits - total_withdrawals
|
||||||
|
) STORED,
|
||||||
|
|
||||||
|
-- Betting and win/loss analytics
|
||||||
|
total_bet_amount NUMERIC(18,2) DEFAULT 0,
|
||||||
|
total_win_amount NUMERIC(18,2) DEFAULT 0,
|
||||||
|
net_result NUMERIC(18,2) GENERATED ALWAYS AS (
|
||||||
|
total_bet_amount - total_win_amount
|
||||||
|
) STORED,
|
||||||
|
|
||||||
|
rounds_played BIGINT DEFAULT 0,
|
||||||
|
avg_bet_size NUMERIC(18,4) GENERATED ALWAYS AS (
|
||||||
|
CASE WHEN rounds_played > 0 THEN total_bet_amount / rounds_played ELSE 0 END
|
||||||
|
) STORED,
|
||||||
|
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMPTZ
|
||||||
|
);
|
||||||
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
-- name: CreateReportRequest :one
|
|
||||||
INSERT INTO report_requests (
|
|
||||||
company_id,
|
|
||||||
requested_by,
|
|
||||||
type,
|
|
||||||
metadata
|
|
||||||
)
|
|
||||||
VALUES ($1, $2, $3, $4)
|
|
||||||
RETURNING *;
|
|
||||||
-- name: GetAllReportRequests :many
|
|
||||||
SELECT *
|
|
||||||
FROM report_request_detail
|
|
||||||
WHERE (
|
|
||||||
company_id = sqlc.narg('company_id')
|
|
||||||
OR sqlc.narg('company_id') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
type = sqlc.narg('type')
|
|
||||||
OR sqlc.narg('type') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
status = sqlc.narg('status')
|
|
||||||
OR sqlc.narg('status') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
requested_by = sqlc.narg('requested_by')
|
|
||||||
OR sqlc.narg('requested_by') IS NULL
|
|
||||||
)
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
|
||||||
-- name: GetTotalReportRequests :one
|
|
||||||
SELECT COUNT(id)
|
|
||||||
FROM report_request_detail
|
|
||||||
WHERE (
|
|
||||||
company_id = sqlc.narg('company_id')
|
|
||||||
OR sqlc.narg('company_id') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
type = sqlc.narg('type')
|
|
||||||
OR sqlc.narg('type') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
status = sqlc.narg('status')
|
|
||||||
OR sqlc.narg('status') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
requested_by = sqlc.narg('requested_by')
|
|
||||||
OR sqlc.narg('requested_by') IS NULL
|
|
||||||
);
|
|
||||||
-- name: GetReportRequestByID :one
|
|
||||||
SELECT *
|
|
||||||
FROM report_request_detail
|
|
||||||
WHERE id = $1;
|
|
||||||
-- name: GetReportRequestByRequestedByID :many
|
|
||||||
SELECT *
|
|
||||||
FROM report_request_detail
|
|
||||||
WHERE requested_by = $1
|
|
||||||
AND (
|
|
||||||
type = sqlc.narg('type')
|
|
||||||
OR sqlc.narg('type') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
status = sqlc.narg('status')
|
|
||||||
OR sqlc.narg('status') IS NULL
|
|
||||||
)
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
|
||||||
-- name: UpdateReportRequest :exec
|
|
||||||
UPDATE report_requests
|
|
||||||
SET file_path = COALESCE(sqlc.narg(file_path), file_path),
|
|
||||||
reject_reason = COALESCE(sqlc.narg(reject_reason), reject_reason),
|
|
||||||
status = COALESCE(sqlc.narg(status), status),
|
|
||||||
completed_at = now()
|
|
||||||
WHERE id = $1;
|
|
||||||
139
db/query/virtual_report.sql
Normal file
139
db/query/virtual_report.sql
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
-- name: CreateFinancialReport :one
|
||||||
|
INSERT INTO virtual_game_financial_reports (
|
||||||
|
game_id, provider_id, report_date, report_type,
|
||||||
|
total_bets, total_wins, created_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, NOW())
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: UpsertFinancialReport :one
|
||||||
|
INSERT INTO virtual_game_financial_reports (
|
||||||
|
game_id, provider_id, report_date, report_type,
|
||||||
|
total_bets, total_wins, created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
|
||||||
|
ON CONFLICT (game_id, provider_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_bets = EXCLUDED.total_bets,
|
||||||
|
total_wins = EXCLUDED.total_wins,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: GetFinancialReportByID :one
|
||||||
|
SELECT * FROM virtual_game_financial_reports
|
||||||
|
WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: GetFinancialReportsForGame :many
|
||||||
|
SELECT * FROM virtual_game_financial_reports
|
||||||
|
WHERE game_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
ORDER BY report_date;
|
||||||
|
|
||||||
|
-- name: GetDailyFinancialReports :many
|
||||||
|
SELECT * FROM virtual_game_financial_reports
|
||||||
|
WHERE report_date = $1
|
||||||
|
AND report_type = 'daily';
|
||||||
|
|
||||||
|
-- name: DeleteFinancialReport :exec
|
||||||
|
DELETE FROM virtual_game_financial_reports
|
||||||
|
WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: CreateCompanyReport :one
|
||||||
|
INSERT INTO virtual_game_company_reports (
|
||||||
|
company_id, provider_id,
|
||||||
|
report_date, report_type,
|
||||||
|
total_bet_amount, total_win_amount, created_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW())
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: UpsertCompanyReport :one
|
||||||
|
INSERT INTO virtual_game_company_reports (
|
||||||
|
company_id, provider_id,
|
||||||
|
report_date, report_type,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
|
||||||
|
ON CONFLICT (company_id, provider_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_bet_amount = EXCLUDED.total_bet_amount,
|
||||||
|
total_win_amount = EXCLUDED.total_win_amount,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: GetCompanyReportByID :one
|
||||||
|
SELECT * FROM virtual_game_company_reports
|
||||||
|
WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: GetCompanyReportsInRange :many
|
||||||
|
SELECT * FROM virtual_game_company_reports
|
||||||
|
WHERE company_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
ORDER BY report_date;
|
||||||
|
|
||||||
|
-- name: GetCompanyProfitTrend :many
|
||||||
|
SELECT report_date, SUM(net_profit) AS total_profit
|
||||||
|
FROM virtual_game_company_reports
|
||||||
|
WHERE company_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
GROUP BY report_date
|
||||||
|
ORDER BY report_date;
|
||||||
|
|
||||||
|
-- name: CreatePlayerActivityReport :one
|
||||||
|
INSERT INTO virtual_game_player_activity_reports (
|
||||||
|
user_id, report_date, report_type,
|
||||||
|
total_deposits, total_withdrawals,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
rounds_played, created_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW())
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: UpsertPlayerActivityReport :one
|
||||||
|
INSERT INTO virtual_game_player_activity_reports (
|
||||||
|
user_id, report_date, report_type,
|
||||||
|
total_deposits, total_withdrawals,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
rounds_played, created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW())
|
||||||
|
ON CONFLICT (user_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_deposits = EXCLUDED.total_deposits,
|
||||||
|
total_withdrawals = EXCLUDED.total_withdrawals,
|
||||||
|
total_bet_amount = EXCLUDED.total_bet_amount,
|
||||||
|
total_win_amount = EXCLUDED.total_win_amount,
|
||||||
|
rounds_played = EXCLUDED.rounds_played,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: GetPlayerActivityByID :one
|
||||||
|
SELECT * FROM virtual_game_player_activity_reports
|
||||||
|
WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: GetPlayerActivityByDate :one
|
||||||
|
SELECT * FROM virtual_game_player_activity_reports
|
||||||
|
WHERE user_id = $1
|
||||||
|
AND report_date = $2
|
||||||
|
AND report_type = $3;
|
||||||
|
|
||||||
|
-- name: GetPlayerActivityRange :many
|
||||||
|
SELECT * FROM virtual_game_player_activity_reports
|
||||||
|
WHERE user_id = $1
|
||||||
|
AND report_date BETWEEN $2 AND $3
|
||||||
|
ORDER BY report_date;
|
||||||
|
|
||||||
|
-- name: GetTopPlayersByNetResult :many
|
||||||
|
SELECT user_id, SUM(net_result) AS total_net
|
||||||
|
FROM virtual_game_player_activity_reports
|
||||||
|
WHERE report_date BETWEEN $1 AND $2
|
||||||
|
GROUP BY user_id
|
||||||
|
ORDER BY total_net DESC
|
||||||
|
LIMIT $3;
|
||||||
|
|
||||||
|
-- name: DeletePlayerActivityReport :exec
|
||||||
|
DELETE FROM virtual_game_player_activity_reports
|
||||||
|
WHERE id = $1;
|
||||||
|
|
@ -1157,6 +1157,20 @@ type VirtualGame struct {
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VirtualGameCompanyReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CompanyID int64 `json:"company_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
NetProfit pgtype.Numeric `json:"net_profit"`
|
||||||
|
ProfitMargin pgtype.Numeric `json:"profit_margin"`
|
||||||
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
type VirtualGameFavourite struct {
|
type VirtualGameFavourite struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
GameID int64 `json:"game_id"`
|
GameID int64 `json:"game_id"`
|
||||||
|
|
@ -1165,6 +1179,20 @@ type VirtualGameFavourite struct {
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VirtualGameFinancialReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
GameID string `json:"game_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBets pgtype.Numeric `json:"total_bets"`
|
||||||
|
TotalWins pgtype.Numeric `json:"total_wins"`
|
||||||
|
Ggr pgtype.Numeric `json:"ggr"`
|
||||||
|
Rtp pgtype.Numeric `json:"rtp"`
|
||||||
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
type VirtualGameHistory struct {
|
type VirtualGameHistory struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
|
|
@ -1182,6 +1210,23 @@ type VirtualGameHistory struct {
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VirtualGamePlayerActivityReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalDeposits pgtype.Numeric `json:"total_deposits"`
|
||||||
|
TotalWithdrawals pgtype.Numeric `json:"total_withdrawals"`
|
||||||
|
NetContribution pgtype.Numeric `json:"net_contribution"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
NetResult pgtype.Numeric `json:"net_result"`
|
||||||
|
RoundsPlayed pgtype.Int8 `json:"rounds_played"`
|
||||||
|
AvgBetSize pgtype.Numeric `json:"avg_bet_size"`
|
||||||
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
type VirtualGameProvider struct {
|
type VirtualGameProvider struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
ProviderID string `json:"provider_id"`
|
ProviderID string `json:"provider_id"`
|
||||||
|
|
|
||||||
721
gen/db/virtual_report.sql.go
Normal file
721
gen/db/virtual_report.sql.go
Normal file
|
|
@ -0,0 +1,721 @@
|
||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.29.0
|
||||||
|
// source: virtual_report.sql
|
||||||
|
|
||||||
|
package dbgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CreateCompanyReport = `-- name: CreateCompanyReport :one
|
||||||
|
INSERT INTO virtual_game_company_reports (
|
||||||
|
company_id, provider_id,
|
||||||
|
report_date, report_type,
|
||||||
|
total_bet_amount, total_win_amount, created_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW())
|
||||||
|
RETURNING id, company_id, provider_id, report_date, report_type, total_bet_amount, total_win_amount, net_profit, profit_margin, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type CreateCompanyReportParams struct {
|
||||||
|
CompanyID int64 `json:"company_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) CreateCompanyReport(ctx context.Context, arg CreateCompanyReportParams) (VirtualGameCompanyReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, CreateCompanyReport,
|
||||||
|
arg.CompanyID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalBetAmount,
|
||||||
|
arg.TotalWinAmount,
|
||||||
|
)
|
||||||
|
var i VirtualGameCompanyReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.CompanyID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetProfit,
|
||||||
|
&i.ProfitMargin,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const CreateFinancialReport = `-- name: CreateFinancialReport :one
|
||||||
|
INSERT INTO virtual_game_financial_reports (
|
||||||
|
game_id, provider_id, report_date, report_type,
|
||||||
|
total_bets, total_wins, created_at
|
||||||
|
) VALUES ($1, $2, $3, $4, $5, $6, NOW())
|
||||||
|
RETURNING id, game_id, provider_id, report_date, report_type, total_bets, total_wins, ggr, rtp, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type CreateFinancialReportParams struct {
|
||||||
|
GameID string `json:"game_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBets pgtype.Numeric `json:"total_bets"`
|
||||||
|
TotalWins pgtype.Numeric `json:"total_wins"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) CreateFinancialReport(ctx context.Context, arg CreateFinancialReportParams) (VirtualGameFinancialReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, CreateFinancialReport,
|
||||||
|
arg.GameID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalBets,
|
||||||
|
arg.TotalWins,
|
||||||
|
)
|
||||||
|
var i VirtualGameFinancialReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.GameID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBets,
|
||||||
|
&i.TotalWins,
|
||||||
|
&i.Ggr,
|
||||||
|
&i.Rtp,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const CreatePlayerActivityReport = `-- name: CreatePlayerActivityReport :one
|
||||||
|
INSERT INTO virtual_game_player_activity_reports (
|
||||||
|
user_id, report_date, report_type,
|
||||||
|
total_deposits, total_withdrawals,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
rounds_played, created_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW())
|
||||||
|
RETURNING id, user_id, report_date, report_type, total_deposits, total_withdrawals, net_contribution, total_bet_amount, total_win_amount, net_result, rounds_played, avg_bet_size, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type CreatePlayerActivityReportParams struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalDeposits pgtype.Numeric `json:"total_deposits"`
|
||||||
|
TotalWithdrawals pgtype.Numeric `json:"total_withdrawals"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
RoundsPlayed pgtype.Int8 `json:"rounds_played"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) CreatePlayerActivityReport(ctx context.Context, arg CreatePlayerActivityReportParams) (VirtualGamePlayerActivityReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, CreatePlayerActivityReport,
|
||||||
|
arg.UserID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalDeposits,
|
||||||
|
arg.TotalWithdrawals,
|
||||||
|
arg.TotalBetAmount,
|
||||||
|
arg.TotalWinAmount,
|
||||||
|
arg.RoundsPlayed,
|
||||||
|
)
|
||||||
|
var i VirtualGamePlayerActivityReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalDeposits,
|
||||||
|
&i.TotalWithdrawals,
|
||||||
|
&i.NetContribution,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetResult,
|
||||||
|
&i.RoundsPlayed,
|
||||||
|
&i.AvgBetSize,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeleteFinancialReport = `-- name: DeleteFinancialReport :exec
|
||||||
|
DELETE FROM virtual_game_financial_reports
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) DeleteFinancialReport(ctx context.Context, id int64) error {
|
||||||
|
_, err := q.db.Exec(ctx, DeleteFinancialReport, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeletePlayerActivityReport = `-- name: DeletePlayerActivityReport :exec
|
||||||
|
DELETE FROM virtual_game_player_activity_reports
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) DeletePlayerActivityReport(ctx context.Context, id int64) error {
|
||||||
|
_, err := q.db.Exec(ctx, DeletePlayerActivityReport, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetCompanyProfitTrend = `-- name: GetCompanyProfitTrend :many
|
||||||
|
SELECT report_date, SUM(net_profit) AS total_profit
|
||||||
|
FROM virtual_game_company_reports
|
||||||
|
WHERE company_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
GROUP BY report_date
|
||||||
|
ORDER BY report_date
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetCompanyProfitTrendParams struct {
|
||||||
|
CompanyID int64 `json:"company_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportDate_2 pgtype.Date `json:"report_date_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCompanyProfitTrendRow struct {
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
TotalProfit int64 `json:"total_profit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetCompanyProfitTrend(ctx context.Context, arg GetCompanyProfitTrendParams) ([]GetCompanyProfitTrendRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetCompanyProfitTrend,
|
||||||
|
arg.CompanyID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportDate_2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetCompanyProfitTrendRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetCompanyProfitTrendRow
|
||||||
|
if err := rows.Scan(&i.ReportDate, &i.TotalProfit); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetCompanyReportByID = `-- name: GetCompanyReportByID :one
|
||||||
|
SELECT id, company_id, provider_id, report_date, report_type, total_bet_amount, total_win_amount, net_profit, profit_margin, created_at, updated_at FROM virtual_game_company_reports
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetCompanyReportByID(ctx context.Context, id int64) (VirtualGameCompanyReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetCompanyReportByID, id)
|
||||||
|
var i VirtualGameCompanyReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.CompanyID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetProfit,
|
||||||
|
&i.ProfitMargin,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetCompanyReportsInRange = `-- name: GetCompanyReportsInRange :many
|
||||||
|
SELECT id, company_id, provider_id, report_date, report_type, total_bet_amount, total_win_amount, net_profit, profit_margin, created_at, updated_at FROM virtual_game_company_reports
|
||||||
|
WHERE company_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
ORDER BY report_date
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetCompanyReportsInRangeParams struct {
|
||||||
|
CompanyID int64 `json:"company_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportDate_2 pgtype.Date `json:"report_date_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetCompanyReportsInRange(ctx context.Context, arg GetCompanyReportsInRangeParams) ([]VirtualGameCompanyReport, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetCompanyReportsInRange,
|
||||||
|
arg.CompanyID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportDate_2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []VirtualGameCompanyReport
|
||||||
|
for rows.Next() {
|
||||||
|
var i VirtualGameCompanyReport
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.CompanyID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetProfit,
|
||||||
|
&i.ProfitMargin,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetDailyFinancialReports = `-- name: GetDailyFinancialReports :many
|
||||||
|
SELECT id, game_id, provider_id, report_date, report_type, total_bets, total_wins, ggr, rtp, created_at, updated_at FROM virtual_game_financial_reports
|
||||||
|
WHERE report_date = $1
|
||||||
|
AND report_type = 'daily'
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetDailyFinancialReports(ctx context.Context, reportDate pgtype.Date) ([]VirtualGameFinancialReport, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetDailyFinancialReports, reportDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []VirtualGameFinancialReport
|
||||||
|
for rows.Next() {
|
||||||
|
var i VirtualGameFinancialReport
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.GameID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBets,
|
||||||
|
&i.TotalWins,
|
||||||
|
&i.Ggr,
|
||||||
|
&i.Rtp,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetFinancialReportByID = `-- name: GetFinancialReportByID :one
|
||||||
|
SELECT id, game_id, provider_id, report_date, report_type, total_bets, total_wins, ggr, rtp, created_at, updated_at FROM virtual_game_financial_reports
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetFinancialReportByID(ctx context.Context, id int64) (VirtualGameFinancialReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetFinancialReportByID, id)
|
||||||
|
var i VirtualGameFinancialReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.GameID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBets,
|
||||||
|
&i.TotalWins,
|
||||||
|
&i.Ggr,
|
||||||
|
&i.Rtp,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetFinancialReportsForGame = `-- name: GetFinancialReportsForGame :many
|
||||||
|
SELECT id, game_id, provider_id, report_date, report_type, total_bets, total_wins, ggr, rtp, created_at, updated_at FROM virtual_game_financial_reports
|
||||||
|
WHERE game_id = $1
|
||||||
|
AND provider_id = $2
|
||||||
|
AND report_date BETWEEN $3 AND $4
|
||||||
|
ORDER BY report_date
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetFinancialReportsForGameParams struct {
|
||||||
|
GameID string `json:"game_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportDate_2 pgtype.Date `json:"report_date_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetFinancialReportsForGame(ctx context.Context, arg GetFinancialReportsForGameParams) ([]VirtualGameFinancialReport, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetFinancialReportsForGame,
|
||||||
|
arg.GameID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportDate_2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []VirtualGameFinancialReport
|
||||||
|
for rows.Next() {
|
||||||
|
var i VirtualGameFinancialReport
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.GameID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBets,
|
||||||
|
&i.TotalWins,
|
||||||
|
&i.Ggr,
|
||||||
|
&i.Rtp,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetPlayerActivityByDate = `-- name: GetPlayerActivityByDate :one
|
||||||
|
SELECT id, user_id, report_date, report_type, total_deposits, total_withdrawals, net_contribution, total_bet_amount, total_win_amount, net_result, rounds_played, avg_bet_size, created_at, updated_at FROM virtual_game_player_activity_reports
|
||||||
|
WHERE user_id = $1
|
||||||
|
AND report_date = $2
|
||||||
|
AND report_type = $3
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetPlayerActivityByDateParams struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetPlayerActivityByDate(ctx context.Context, arg GetPlayerActivityByDateParams) (VirtualGamePlayerActivityReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetPlayerActivityByDate, arg.UserID, arg.ReportDate, arg.ReportType)
|
||||||
|
var i VirtualGamePlayerActivityReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalDeposits,
|
||||||
|
&i.TotalWithdrawals,
|
||||||
|
&i.NetContribution,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetResult,
|
||||||
|
&i.RoundsPlayed,
|
||||||
|
&i.AvgBetSize,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetPlayerActivityByID = `-- name: GetPlayerActivityByID :one
|
||||||
|
SELECT id, user_id, report_date, report_type, total_deposits, total_withdrawals, net_contribution, total_bet_amount, total_win_amount, net_result, rounds_played, avg_bet_size, created_at, updated_at FROM virtual_game_player_activity_reports
|
||||||
|
WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetPlayerActivityByID(ctx context.Context, id int64) (VirtualGamePlayerActivityReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetPlayerActivityByID, id)
|
||||||
|
var i VirtualGamePlayerActivityReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalDeposits,
|
||||||
|
&i.TotalWithdrawals,
|
||||||
|
&i.NetContribution,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetResult,
|
||||||
|
&i.RoundsPlayed,
|
||||||
|
&i.AvgBetSize,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetPlayerActivityRange = `-- name: GetPlayerActivityRange :many
|
||||||
|
SELECT id, user_id, report_date, report_type, total_deposits, total_withdrawals, net_contribution, total_bet_amount, total_win_amount, net_result, rounds_played, avg_bet_size, created_at, updated_at FROM virtual_game_player_activity_reports
|
||||||
|
WHERE user_id = $1
|
||||||
|
AND report_date BETWEEN $2 AND $3
|
||||||
|
ORDER BY report_date
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetPlayerActivityRangeParams struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportDate_2 pgtype.Date `json:"report_date_2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetPlayerActivityRange(ctx context.Context, arg GetPlayerActivityRangeParams) ([]VirtualGamePlayerActivityReport, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetPlayerActivityRange, arg.UserID, arg.ReportDate, arg.ReportDate_2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []VirtualGamePlayerActivityReport
|
||||||
|
for rows.Next() {
|
||||||
|
var i VirtualGamePlayerActivityReport
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalDeposits,
|
||||||
|
&i.TotalWithdrawals,
|
||||||
|
&i.NetContribution,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetResult,
|
||||||
|
&i.RoundsPlayed,
|
||||||
|
&i.AvgBetSize,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetTopPlayersByNetResult = `-- name: GetTopPlayersByNetResult :many
|
||||||
|
SELECT user_id, SUM(net_result) AS total_net
|
||||||
|
FROM virtual_game_player_activity_reports
|
||||||
|
WHERE report_date BETWEEN $1 AND $2
|
||||||
|
GROUP BY user_id
|
||||||
|
ORDER BY total_net DESC
|
||||||
|
LIMIT $3
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetTopPlayersByNetResultParams struct {
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportDate_2 pgtype.Date `json:"report_date_2"`
|
||||||
|
Limit int32 `json:"limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetTopPlayersByNetResultRow struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
TotalNet int64 `json:"total_net"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetTopPlayersByNetResult(ctx context.Context, arg GetTopPlayersByNetResultParams) ([]GetTopPlayersByNetResultRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetTopPlayersByNetResult, arg.ReportDate, arg.ReportDate_2, arg.Limit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetTopPlayersByNetResultRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetTopPlayersByNetResultRow
|
||||||
|
if err := rows.Scan(&i.UserID, &i.TotalNet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const UpsertCompanyReport = `-- name: UpsertCompanyReport :one
|
||||||
|
INSERT INTO virtual_game_company_reports (
|
||||||
|
company_id, provider_id,
|
||||||
|
report_date, report_type,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
|
||||||
|
ON CONFLICT (company_id, provider_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_bet_amount = EXCLUDED.total_bet_amount,
|
||||||
|
total_win_amount = EXCLUDED.total_win_amount,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING id, company_id, provider_id, report_date, report_type, total_bet_amount, total_win_amount, net_profit, profit_margin, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpsertCompanyReportParams struct {
|
||||||
|
CompanyID int64 `json:"company_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpsertCompanyReport(ctx context.Context, arg UpsertCompanyReportParams) (VirtualGameCompanyReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, UpsertCompanyReport,
|
||||||
|
arg.CompanyID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalBetAmount,
|
||||||
|
arg.TotalWinAmount,
|
||||||
|
)
|
||||||
|
var i VirtualGameCompanyReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.CompanyID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetProfit,
|
||||||
|
&i.ProfitMargin,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const UpsertFinancialReport = `-- name: UpsertFinancialReport :one
|
||||||
|
INSERT INTO virtual_game_financial_reports (
|
||||||
|
game_id, provider_id, report_date, report_type,
|
||||||
|
total_bets, total_wins, created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW())
|
||||||
|
ON CONFLICT (game_id, provider_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_bets = EXCLUDED.total_bets,
|
||||||
|
total_wins = EXCLUDED.total_wins,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING id, game_id, provider_id, report_date, report_type, total_bets, total_wins, ggr, rtp, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpsertFinancialReportParams struct {
|
||||||
|
GameID string `json:"game_id"`
|
||||||
|
ProviderID string `json:"provider_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalBets pgtype.Numeric `json:"total_bets"`
|
||||||
|
TotalWins pgtype.Numeric `json:"total_wins"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpsertFinancialReport(ctx context.Context, arg UpsertFinancialReportParams) (VirtualGameFinancialReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, UpsertFinancialReport,
|
||||||
|
arg.GameID,
|
||||||
|
arg.ProviderID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalBets,
|
||||||
|
arg.TotalWins,
|
||||||
|
)
|
||||||
|
var i VirtualGameFinancialReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.GameID,
|
||||||
|
&i.ProviderID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalBets,
|
||||||
|
&i.TotalWins,
|
||||||
|
&i.Ggr,
|
||||||
|
&i.Rtp,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const UpsertPlayerActivityReport = `-- name: UpsertPlayerActivityReport :one
|
||||||
|
INSERT INTO virtual_game_player_activity_reports (
|
||||||
|
user_id, report_date, report_type,
|
||||||
|
total_deposits, total_withdrawals,
|
||||||
|
total_bet_amount, total_win_amount,
|
||||||
|
rounds_played, created_at, updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW())
|
||||||
|
ON CONFLICT (user_id, report_date, report_type)
|
||||||
|
DO UPDATE SET
|
||||||
|
total_deposits = EXCLUDED.total_deposits,
|
||||||
|
total_withdrawals = EXCLUDED.total_withdrawals,
|
||||||
|
total_bet_amount = EXCLUDED.total_bet_amount,
|
||||||
|
total_win_amount = EXCLUDED.total_win_amount,
|
||||||
|
rounds_played = EXCLUDED.rounds_played,
|
||||||
|
updated_at = NOW()
|
||||||
|
RETURNING id, user_id, report_date, report_type, total_deposits, total_withdrawals, net_contribution, total_bet_amount, total_win_amount, net_result, rounds_played, avg_bet_size, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpsertPlayerActivityReportParams struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
ReportDate pgtype.Date `json:"report_date"`
|
||||||
|
ReportType string `json:"report_type"`
|
||||||
|
TotalDeposits pgtype.Numeric `json:"total_deposits"`
|
||||||
|
TotalWithdrawals pgtype.Numeric `json:"total_withdrawals"`
|
||||||
|
TotalBetAmount pgtype.Numeric `json:"total_bet_amount"`
|
||||||
|
TotalWinAmount pgtype.Numeric `json:"total_win_amount"`
|
||||||
|
RoundsPlayed pgtype.Int8 `json:"rounds_played"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpsertPlayerActivityReport(ctx context.Context, arg UpsertPlayerActivityReportParams) (VirtualGamePlayerActivityReport, error) {
|
||||||
|
row := q.db.QueryRow(ctx, UpsertPlayerActivityReport,
|
||||||
|
arg.UserID,
|
||||||
|
arg.ReportDate,
|
||||||
|
arg.ReportType,
|
||||||
|
arg.TotalDeposits,
|
||||||
|
arg.TotalWithdrawals,
|
||||||
|
arg.TotalBetAmount,
|
||||||
|
arg.TotalWinAmount,
|
||||||
|
arg.RoundsPlayed,
|
||||||
|
)
|
||||||
|
var i VirtualGamePlayerActivityReport
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.ReportDate,
|
||||||
|
&i.ReportType,
|
||||||
|
&i.TotalDeposits,
|
||||||
|
&i.TotalWithdrawals,
|
||||||
|
&i.NetContribution,
|
||||||
|
&i.TotalBetAmount,
|
||||||
|
&i.TotalWinAmount,
|
||||||
|
&i.NetResult,
|
||||||
|
&i.RoundsPlayed,
|
||||||
|
&i.AvgBetSize,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
149
internal/domain/virtual_report.go
Normal file
149
internal/domain/virtual_report.go
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FinancialReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
GameID string `json:"gameId"`
|
||||||
|
ProviderID string `json:"providerId"`
|
||||||
|
ReportDate string `json:"reportDate"` // YYYY-MM-DD
|
||||||
|
ReportType string `json:"reportType"`
|
||||||
|
TotalBets float64 `json:"totalBets"`
|
||||||
|
TotalWins float64 `json:"totalWins"`
|
||||||
|
GGR float64 `json:"ggr"`
|
||||||
|
RTP float64 `json:"rtp"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertDBFinancialReport(dbReport dbgen.VirtualGameFinancialReport) FinancialReport {
|
||||||
|
return FinancialReport{
|
||||||
|
ID: dbReport.ID,
|
||||||
|
GameID: dbReport.GameID,
|
||||||
|
ProviderID: dbReport.ProviderID,
|
||||||
|
ReportDate: dbReport.ReportDate.Time.Format("2006-01-02"),
|
||||||
|
ReportType: dbReport.ReportType,
|
||||||
|
TotalBets: float64(dbReport.TotalBets.Exp),
|
||||||
|
TotalWins: float64(dbReport.TotalWins.Exp),
|
||||||
|
GGR: float64(dbReport.Ggr.Exp),
|
||||||
|
RTP: float64(dbReport.Rtp.Exp),
|
||||||
|
CreatedAt: dbReport.CreatedAt.Time,
|
||||||
|
UpdatedAt: &dbReport.UpdatedAt.Time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompanyReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CompanyID int64 `json:"companyId"`
|
||||||
|
ProviderID string `json:"providerId"`
|
||||||
|
ReportDate string `json:"reportDate"` // YYYY-MM-DD
|
||||||
|
ReportType string `json:"reportType"`
|
||||||
|
TotalBetAmount float64 `json:"totalBetAmount"`
|
||||||
|
TotalWinAmount float64 `json:"totalWinAmount"`
|
||||||
|
NetProfit float64 `json:"netProfit"`
|
||||||
|
ProfitMargin float64 `json:"profitMargin"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertDBCompanyReport converts the SQLC generated CompanyReport struct to domain.CompanyReport
|
||||||
|
func ConvertDBCompanyReport(dbReport dbgen.VirtualGameCompanyReport) CompanyReport {
|
||||||
|
var updatedAt *time.Time
|
||||||
|
if !dbReport.UpdatedAt.Time.IsZero() {
|
||||||
|
updatedAt = &dbReport.UpdatedAt.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert big.Int-backed numeric fields to float64 safely
|
||||||
|
var totalBetAmount float64
|
||||||
|
if dbReport.TotalBetAmount.Int != nil {
|
||||||
|
if f, _ := new(big.Float).SetInt(dbReport.TotalBetAmount.Int).Float64(); true {
|
||||||
|
totalBetAmount = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalWinAmount float64
|
||||||
|
if dbReport.TotalWinAmount.Int != nil {
|
||||||
|
if f, _ := new(big.Float).SetInt(dbReport.TotalWinAmount.Int).Float64(); true {
|
||||||
|
totalWinAmount = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var netProfit float64
|
||||||
|
if dbReport.NetProfit.Int != nil {
|
||||||
|
if f, _ := new(big.Float).SetInt(dbReport.NetProfit.Int).Float64(); true {
|
||||||
|
netProfit = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var profitMargin float64
|
||||||
|
if dbReport.ProfitMargin.Int != nil {
|
||||||
|
if f, _ := new(big.Float).SetInt(dbReport.ProfitMargin.Int).Float64(); true {
|
||||||
|
profitMargin = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompanyReport{
|
||||||
|
ID: dbReport.ID,
|
||||||
|
CompanyID: dbReport.CompanyID,
|
||||||
|
ProviderID: dbReport.ProviderID,
|
||||||
|
ReportDate: dbReport.ReportDate.Time.Format("2006-01-02"),
|
||||||
|
ReportType: dbReport.ReportType,
|
||||||
|
TotalBetAmount: totalBetAmount,
|
||||||
|
TotalWinAmount: totalWinAmount,
|
||||||
|
NetProfit: netProfit,
|
||||||
|
ProfitMargin: profitMargin,
|
||||||
|
CreatedAt: dbReport.CreatedAt.Time,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompanyProfitTrend struct {
|
||||||
|
ReportDate string `json:"reportDate"`
|
||||||
|
TotalProfit float64 `json:"totalProfit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlayerActivityReport struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
UserID int64 `json:"userId"`
|
||||||
|
ReportDate string `json:"reportDate"` // YYYY-MM-DD
|
||||||
|
ReportType string `json:"reportType"`
|
||||||
|
TotalDeposits float64 `json:"totalDeposits"`
|
||||||
|
TotalWithdrawals float64 `json:"totalWithdrawals"`
|
||||||
|
NetContribution float64 `json:"netContribution"`
|
||||||
|
TotalBetAmount float64 `json:"totalBetAmount"`
|
||||||
|
TotalWinAmount float64 `json:"totalWinAmount"`
|
||||||
|
NetResult float64 `json:"netResult"`
|
||||||
|
RoundsPlayed int64 `json:"roundsPlayed"`
|
||||||
|
AvgBetSize float64 `json:"avgBetSize"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertDBPlayerActivityReport(dbReport dbgen.VirtualGamePlayerActivityReport) PlayerActivityReport {
|
||||||
|
return PlayerActivityReport{
|
||||||
|
ID: dbReport.ID,
|
||||||
|
UserID: dbReport.UserID,
|
||||||
|
ReportDate: dbReport.ReportDate.Time.Format("2006-01-02"),
|
||||||
|
ReportType: dbReport.ReportType,
|
||||||
|
TotalDeposits: float64(dbReport.TotalDeposits.Exp),
|
||||||
|
TotalWithdrawals: float64(dbReport.TotalWithdrawals.Exp),
|
||||||
|
NetContribution: float64(dbReport.NetContribution.Exp),
|
||||||
|
TotalBetAmount: float64(dbReport.TotalBetAmount.Exp),
|
||||||
|
TotalWinAmount: float64(dbReport.TotalWinAmount.Exp),
|
||||||
|
NetResult: float64(dbReport.NetResult.Exp),
|
||||||
|
RoundsPlayed: dbReport.RoundsPlayed.Int64,
|
||||||
|
AvgBetSize: float64(dbReport.AvgBetSize.Exp),
|
||||||
|
CreatedAt: dbReport.CreatedAt.Time,
|
||||||
|
UpdatedAt: &dbReport.UpdatedAt.Time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopPlayerNetResult struct {
|
||||||
|
UserID int64 `json:"userId"`
|
||||||
|
TotalNet float64 `json:"totalNet"`
|
||||||
|
}
|
||||||
27
internal/ports/virtual_report.go
Normal file
27
internal/ports/virtual_report.go
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VirtualGameReportStore interface {
|
||||||
|
CreateFinancialReport(ctx context.Context, report domain.FinancialReport) (domain.FinancialReport, error)
|
||||||
|
UpsertFinancialReport(ctx context.Context, report domain.FinancialReport) (domain.FinancialReport, error)
|
||||||
|
GetFinancialReportByID(ctx context.Context, id int64) (domain.FinancialReport, error)
|
||||||
|
GetFinancialReportsForGame(ctx context.Context, gameID, providerID string, from, to string) ([]domain.FinancialReport, error)
|
||||||
|
GetDailyFinancialReports(ctx context.Context, reportDate string) ([]domain.FinancialReport, error)
|
||||||
|
DeleteFinancialReport(ctx context.Context, id int64) error
|
||||||
|
CreateCompanyReport(ctx context.Context, report domain.CompanyReport) (domain.CompanyReport, error)
|
||||||
|
UpsertCompanyReport(ctx context.Context, report domain.CompanyReport) (domain.CompanyReport, error)
|
||||||
|
GetCompanyReportByID(ctx context.Context, id int64) (domain.CompanyReport, error)
|
||||||
|
GetCompanyReportsInRange(ctx context.Context, companyID int64, providerID string, startDate, endDate string) ([]domain.CompanyReport, error)
|
||||||
|
GetCompanyProfitTrend(ctx context.Context, companyID int64, providerID string, startDate, endDate string) ([]domain.CompanyProfitTrend, error)
|
||||||
|
CreatePlayerActivityReport(ctx context.Context, report domain.PlayerActivityReport) (domain.PlayerActivityReport, error)
|
||||||
|
GetPlayerActivityByID(ctx context.Context, id int64) (domain.PlayerActivityReport, error)
|
||||||
|
GetPlayerActivityByDate(ctx context.Context, userID int64, reportDate, reportType string) (domain.PlayerActivityReport, error)
|
||||||
|
GetPlayerActivityRange(ctx context.Context, userID int64, startDate, endDate string) ([]domain.PlayerActivityReport, error)
|
||||||
|
GetTopPlayersByNetResult(ctx context.Context, startDate, endDate string, limit int) ([]domain.TopPlayerNetResult, error)
|
||||||
|
DeletePlayerActivityReport(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
@ -122,6 +122,14 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
|
||||||
CreatedAfter: filter.CreatedAfter.ToPG(),
|
CreatedAfter: filter.CreatedAfter.ToPG(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// domain.MongoDBLogger.Error("failed to get all bets",
|
||||||
|
// zap.Any("filter", filter),
|
||||||
|
// zap.Error(err),
|
||||||
|
// )
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
var result []domain.GetBet = make([]domain.GetBet, 0, len(bets))
|
var result []domain.GetBet = make([]domain.GetBet, 0, len(bets))
|
||||||
for _, bet := range bets {
|
for _, bet := range bets {
|
||||||
result = append(result, domain.ConvertDBBetWithOutcomes(bet))
|
result = append(result, domain.ConvertDBBetWithOutcomes(bet))
|
||||||
|
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
package repository
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Interface for ReportStore
|
|
||||||
func NewReportStore(s *Store) ports.ReportStore { return s }
|
|
||||||
|
|
||||||
func (s *Store) CreateReportRequest(ctx context.Context, report domain.CreateReportRequest) (domain.ReportRequest, error) {
|
|
||||||
reportMetadata, err := report.Metadata.ToPG()
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportRequest{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dbReportRequest, err := s.queries.CreateReportRequest(ctx, dbgen.CreateReportRequestParams{
|
|
||||||
CompanyID: report.CompanyID.ToPG(),
|
|
||||||
RequestedBy: report.RequestedBy.ToPG(),
|
|
||||||
Type: string(report.Type),
|
|
||||||
Metadata: reportMetadata,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportRequest{}, fmt.Errorf("failed to create report request: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return domain.ConvertDBReportRequest(dbReportRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllReportRequests(ctx context.Context, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, int64, error) {
|
|
||||||
dbReportRequests, err := s.queries.GetAllReportRequests(ctx, dbgen.GetAllReportRequestsParams{
|
|
||||||
CompanyID: filter.CompanyID.ToPG(),
|
|
||||||
Type: filter.Type.ToPG(),
|
|
||||||
Status: filter.Status.ToPG(),
|
|
||||||
Limit: filter.Limit.ToPG(),
|
|
||||||
Offset: pgtype.Int4{
|
|
||||||
Int32: int32(filter.Offset.Value * filter.Limit.Value),
|
|
||||||
Valid: filter.Offset.Valid,
|
|
||||||
},
|
|
||||||
RequestedBy: filter.RequestedBy.ToPG(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
total, err := s.queries.GetTotalReportRequests(ctx, dbgen.GetTotalReportRequestsParams{
|
|
||||||
CompanyID: filter.CompanyID.ToPG(),
|
|
||||||
Type: filter.Type.ToPG(),
|
|
||||||
Status: filter.Status.ToPG(),
|
|
||||||
RequestedBy: filter.RequestedBy.ToPG(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
result, err := domain.ConvertDBReportRequestDetailList(dbReportRequests)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return result, total, nil
|
|
||||||
}
|
|
||||||
func (s *Store) GetReportRequestByRequestedByID(ctx context.Context, requestedBy int64, filter domain.ReportRequestFilter) ([]domain.ReportRequestDetail, error) {
|
|
||||||
dbReportRequests, err := s.queries.GetReportRequestByRequestedByID(ctx, dbgen.GetReportRequestByRequestedByIDParams{
|
|
||||||
RequestedBy: pgtype.Int8{
|
|
||||||
Int64: requestedBy,
|
|
||||||
Valid: true,
|
|
||||||
},
|
|
||||||
Type: filter.Type.ToPG(),
|
|
||||||
Status: filter.Status.ToPG(),
|
|
||||||
Limit: filter.Limit.ToPG(),
|
|
||||||
Offset: pgtype.Int4{
|
|
||||||
Int32: int32(filter.Offset.Value * filter.Limit.Value),
|
|
||||||
Valid: filter.Offset.Valid,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return domain.ConvertDBReportRequestDetailList(dbReportRequests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetReportRequestByID(ctx context.Context, ID int64) (domain.ReportRequestDetail, error) {
|
|
||||||
dbReportRequest, err := s.queries.GetReportRequestByID(ctx, ID)
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportRequestDetail{}, err
|
|
||||||
}
|
|
||||||
return domain.ConvertDBReportRequestDetail(dbReportRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) UpdateReportRequest(ctx context.Context, report domain.UpdateRequestRequest) error {
|
|
||||||
err := s.queries.UpdateReportRequest(ctx, dbgen.UpdateReportRequestParams{
|
|
||||||
ID: report.ID,
|
|
||||||
FilePath: report.FilePath.ToPG(),
|
|
||||||
RejectReason: report.RejectReason.ToPG(),
|
|
||||||
Status: report.Status.ToPG(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to update report request: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
450
internal/repository/virtual_report.go
Normal file
450
internal/repository/virtual_report.go
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewVirtualGameReportStore returns a new VirtualGameReportStore interface
|
||||||
|
func NewVirtualGameReportStore(s *Store) ports.VirtualGameReportStore {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------- Financial Reports -------------------
|
||||||
|
func (s *Store) CreateFinancialReport(ctx context.Context, report domain.FinancialReport) (domain.FinancialReport, error) {
|
||||||
|
// pgtype.Numeric no longer exposes a Set method in this pgx version;
|
||||||
|
// use zero-value pgtype.Numeric here (or replace with a proper conversion helper).
|
||||||
|
totalBets := pgtype.Numeric{}
|
||||||
|
totalWins := pgtype.Numeric{}
|
||||||
|
|
||||||
|
// parse report.ReportDate (try RFC3339 then YYYY-MM-DD)
|
||||||
|
t, err := time.Parse(time.RFC3339, report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
t, err = time.Parse("2006-01-02", report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.FinancialReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReport, err := s.queries.CreateFinancialReport(ctx, dbgen.CreateFinancialReportParams{
|
||||||
|
GameID: report.GameID,
|
||||||
|
ProviderID: report.ProviderID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalBets: totalBets,
|
||||||
|
TotalWins: totalWins,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return domain.FinancialReport{}, fmt.Errorf("failed to create financial report: %w", err)
|
||||||
|
}
|
||||||
|
return domain.ConvertDBFinancialReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) UpsertFinancialReport(ctx context.Context, report domain.FinancialReport) (domain.FinancialReport, error) {
|
||||||
|
totalBets := pgtype.Numeric{}
|
||||||
|
totalWins := pgtype.Numeric{}
|
||||||
|
|
||||||
|
// parse report.ReportDate
|
||||||
|
t, err := time.Parse(time.RFC3339, report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
t, err = time.Parse("2006-01-02", report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.FinancialReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReport, err := s.queries.UpsertFinancialReport(ctx, dbgen.UpsertFinancialReportParams{
|
||||||
|
GameID: report.GameID,
|
||||||
|
ProviderID: report.ProviderID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalBets: totalBets,
|
||||||
|
TotalWins: totalWins,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return domain.FinancialReport{}, fmt.Errorf("failed to upsert financial report: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBFinancialReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFinancialReportByID fetches a single report by its ID
|
||||||
|
func (s *Store) GetFinancialReportByID(ctx context.Context, id int64) (domain.FinancialReport, error) {
|
||||||
|
dbReport, err := s.queries.GetFinancialReportByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return domain.FinancialReport{}, fmt.Errorf("failed to get financial report by ID: %w", err)
|
||||||
|
}
|
||||||
|
return domain.ConvertDBFinancialReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFinancialReportsForGame fetches all reports for a specific game + provider in a date range
|
||||||
|
func (s *Store) GetFinancialReportsForGame(ctx context.Context, gameID, providerID string, from, to string) ([]domain.FinancialReport, error) {
|
||||||
|
fromDate, err := time.Parse("2006-01-02", from)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid from date: %w", err)
|
||||||
|
}
|
||||||
|
toDate, err := time.Parse("2006-01-02", to)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid to date: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReports, err := s.queries.GetFinancialReportsForGame(ctx, dbgen.GetFinancialReportsForGameParams{
|
||||||
|
GameID: gameID,
|
||||||
|
ProviderID: providerID,
|
||||||
|
ReportDate: pgtype.Date{Time: fromDate},
|
||||||
|
ReportDate_2: pgtype.Date{Time: toDate},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get financial reports for game: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []domain.FinancialReport
|
||||||
|
for _, r := range dbReports {
|
||||||
|
result = append(result, domain.ConvertDBFinancialReport(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetDailyFinancialReports(ctx context.Context, reportDate string) ([]domain.FinancialReport, error) {
|
||||||
|
t, err := time.Parse("2006-01-02", reportDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReports, err := s.queries.GetDailyFinancialReports(ctx, pgtype.Date{Time: t})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get daily financial reports: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []domain.FinancialReport
|
||||||
|
for _, r := range dbReports {
|
||||||
|
result = append(result, domain.ConvertDBFinancialReport(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFinancialReport deletes a financial report by ID
|
||||||
|
func (s *Store) DeleteFinancialReport(ctx context.Context, id int64) error {
|
||||||
|
err := s.queries.DeleteFinancialReport(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete financial report: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCompanyReport inserts a new company-level financial report
|
||||||
|
func (s *Store) CreateCompanyReport(ctx context.Context, report domain.CompanyReport) (domain.CompanyReport, error) {
|
||||||
|
// parse report date
|
||||||
|
t, err := time.Parse("2006-01-02", report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.CompanyReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReport, err := s.queries.CreateCompanyReport(ctx, dbgen.CreateCompanyReportParams{
|
||||||
|
CompanyID: report.CompanyID,
|
||||||
|
ProviderID: report.ProviderID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalBetAmount: pgtype.Numeric{}, // zero value; set actual value if required
|
||||||
|
TotalWinAmount: pgtype.Numeric{},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return domain.CompanyReport{}, fmt.Errorf("failed to create company report: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBCompanyReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) UpsertCompanyReport(ctx context.Context, report domain.CompanyReport) (domain.CompanyReport, error) {
|
||||||
|
// Convert report date
|
||||||
|
t, err := time.Parse("2006-01-02", report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
t, err = time.Parse(time.RFC3339, report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.CompanyReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReport, err := s.queries.UpsertCompanyReport(ctx, dbgen.UpsertCompanyReportParams{
|
||||||
|
CompanyID: report.CompanyID,
|
||||||
|
ProviderID: report.ProviderID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalBetAmount: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalBetAmount)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
TotalWinAmount: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalWinAmount)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return domain.CompanyReport{}, fmt.Errorf("failed to upsert company report: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBCompanyReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetCompanyReportByID(ctx context.Context, id int64) (domain.CompanyReport, error) {
|
||||||
|
dbReport, err := s.queries.GetCompanyReportByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return domain.CompanyReport{}, fmt.Errorf("failed to get company report by ID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBCompanyReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetCompanyReportsInRange(ctx context.Context, companyID int64, providerID string, startDate, endDate string) ([]domain.CompanyReport, error) {
|
||||||
|
start, err := time.Parse("2006-01-02", startDate)
|
||||||
|
if err != nil {
|
||||||
|
start, err = time.Parse(time.RFC3339, startDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid start date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end, err := time.Parse("2006-01-02", endDate)
|
||||||
|
if err != nil {
|
||||||
|
end, err = time.Parse(time.RFC3339, endDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid end date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReports, err := s.queries.GetCompanyReportsInRange(ctx, dbgen.GetCompanyReportsInRangeParams{
|
||||||
|
CompanyID: companyID,
|
||||||
|
ProviderID: providerID,
|
||||||
|
ReportDate: pgtype.Date{Time: start},
|
||||||
|
ReportDate_2: pgtype.Date{Time: end},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get company reports in range: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reports := make([]domain.CompanyReport, 0, len(dbReports))
|
||||||
|
for _, r := range dbReports {
|
||||||
|
reports = append(reports, domain.ConvertDBCompanyReport(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reports, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetCompanyProfitTrend(ctx context.Context, companyID int64, providerID string, startDate, endDate string) ([]domain.CompanyProfitTrend, error) {
|
||||||
|
start, err := time.Parse("2006-01-02", startDate)
|
||||||
|
if err != nil {
|
||||||
|
start, err = time.Parse(time.RFC3339, startDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid start date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end, err := time.Parse("2006-01-02", endDate)
|
||||||
|
if err != nil {
|
||||||
|
end, err = time.Parse(time.RFC3339, endDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid end date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := s.queries.GetCompanyProfitTrend(ctx, dbgen.GetCompanyProfitTrendParams{
|
||||||
|
CompanyID: companyID,
|
||||||
|
ProviderID: providerID,
|
||||||
|
ReportDate: pgtype.Date{Time: start},
|
||||||
|
ReportDate_2: pgtype.Date{Time: end},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get company profit trend: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
trends := make([]domain.CompanyProfitTrend, 0, len(rows))
|
||||||
|
for _, r := range rows {
|
||||||
|
trends = append(trends, domain.CompanyProfitTrend{
|
||||||
|
ReportDate: r.ReportDate.Time.Format("2006-01-02"),
|
||||||
|
TotalProfit: float64(r.TotalProfit),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return trends, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePlayerActivityReport inserts a new player activity report
|
||||||
|
func (s *Store) CreatePlayerActivityReport(ctx context.Context, report domain.PlayerActivityReport) (domain.PlayerActivityReport, error) {
|
||||||
|
t, err := time.Parse("2006-01-02", report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
t, err = time.Parse(time.RFC3339, report.ReportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerActivityReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createParams := dbgen.CreatePlayerActivityReportParams{
|
||||||
|
UserID: report.UserID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalDeposits: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalDeposits)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
TotalWithdrawals: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalWithdrawals)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
TotalBetAmount: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalBetAmount)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
TotalWinAmount: func() pgtype.Numeric {
|
||||||
|
var n pgtype.Numeric
|
||||||
|
_ = n.Scan(report.TotalWinAmount)
|
||||||
|
return n
|
||||||
|
}(),
|
||||||
|
RoundsPlayed: pgtype.Int8{Int64: int64(report.RoundsPlayed)},
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbReport dbgen.VirtualGamePlayerActivityReport
|
||||||
|
dbReport, err = s.queries.CreatePlayerActivityReport(ctx, createParams)
|
||||||
|
if err != nil {
|
||||||
|
// try upsert as a fallback
|
||||||
|
upsertParams := dbgen.UpsertPlayerActivityReportParams{
|
||||||
|
UserID: report.UserID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: report.ReportType,
|
||||||
|
TotalDeposits: pgtype.Numeric{Exp: int32(report.TotalDeposits)},
|
||||||
|
TotalWithdrawals: pgtype.Numeric{Exp: int32(report.TotalWithdrawals)},
|
||||||
|
TotalBetAmount: pgtype.Numeric{Exp: int32(report.TotalBetAmount)},
|
||||||
|
TotalWinAmount: pgtype.Numeric{Exp: int32(report.TotalWinAmount)},
|
||||||
|
RoundsPlayed: pgtype.Int8{Int64: int64(report.RoundsPlayed)},
|
||||||
|
}
|
||||||
|
dbReport, err = s.queries.UpsertPlayerActivityReport(ctx, upsertParams)
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerActivityReport{}, fmt.Errorf("failed to create or upsert player activity report: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBPlayerActivityReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetPlayerActivityByID(ctx context.Context, id int64) (domain.PlayerActivityReport, error) {
|
||||||
|
dbReport, err := s.queries.GetPlayerActivityByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerActivityReport{}, err
|
||||||
|
}
|
||||||
|
return domain.ConvertDBPlayerActivityReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerActivityByDate fetches a player activity report for a specific user and date
|
||||||
|
func (s *Store) GetPlayerActivityByDate(ctx context.Context, userID int64, reportDate, reportType string) (domain.PlayerActivityReport, error) {
|
||||||
|
t, err := time.Parse("2006-01-02", reportDate)
|
||||||
|
if err != nil {
|
||||||
|
t, err = time.Parse(time.RFC3339, reportDate)
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerActivityReport{}, fmt.Errorf("invalid report date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReport, err := s.queries.GetPlayerActivityByDate(ctx, dbgen.GetPlayerActivityByDateParams{
|
||||||
|
UserID: userID,
|
||||||
|
ReportDate: pgtype.Date{Time: t},
|
||||||
|
ReportType: reportType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return domain.PlayerActivityReport{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.ConvertDBPlayerActivityReport(dbReport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerActivityRange fetches all activity reports for a user in a date range
|
||||||
|
func (s *Store) GetPlayerActivityRange(ctx context.Context, userID int64, startDate, endDate string) ([]domain.PlayerActivityReport, error) {
|
||||||
|
start, err := time.Parse("2006-01-02", startDate)
|
||||||
|
if err != nil {
|
||||||
|
start, err = time.Parse(time.RFC3339, startDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid start date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end, err := time.Parse("2006-01-02", endDate)
|
||||||
|
if err != nil {
|
||||||
|
end, err = time.Parse(time.RFC3339, endDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid end date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbReports, err := s.queries.GetPlayerActivityRange(ctx, dbgen.GetPlayerActivityRangeParams{
|
||||||
|
UserID: userID,
|
||||||
|
ReportDate: pgtype.Date{Time: start},
|
||||||
|
ReportDate_2: pgtype.Date{Time: end},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
activities := make([]domain.PlayerActivityReport, 0, len(dbReports))
|
||||||
|
for _, r := range dbReports {
|
||||||
|
activities = append(activities, domain.ConvertDBPlayerActivityReport(r))
|
||||||
|
}
|
||||||
|
return activities, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopPlayersByNetResult returns the top N players by net result in a date range
|
||||||
|
func (s *Store) GetTopPlayersByNetResult(ctx context.Context, startDate, endDate string, limit int) ([]domain.TopPlayerNetResult, error) {
|
||||||
|
start, err := time.Parse("2006-01-02", startDate)
|
||||||
|
if err != nil {
|
||||||
|
start, err = time.Parse(time.RFC3339, startDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid start date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end, err := time.Parse("2006-01-02", endDate)
|
||||||
|
if err != nil {
|
||||||
|
end, err = time.Parse(time.RFC3339, endDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid end date: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := s.conn.Query(ctx, `SELECT user_id, SUM(net_result) AS total_net
|
||||||
|
FROM virtual_game_player_activity_reports
|
||||||
|
WHERE report_date BETWEEN $1 AND $2
|
||||||
|
GROUP BY user_id
|
||||||
|
ORDER BY total_net DESC
|
||||||
|
LIMIT $3`, start, end, limit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch top players: %w", err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var topPlayers []domain.TopPlayerNetResult
|
||||||
|
for rows.Next() {
|
||||||
|
var tp domain.TopPlayerNetResult
|
||||||
|
var totalNet pgtype.Numeric
|
||||||
|
if err := rows.Scan(&tp.UserID, &totalNet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tp.TotalNet = float64(totalNet.Exp)
|
||||||
|
topPlayers = append(topPlayers, tp)
|
||||||
|
}
|
||||||
|
return topPlayers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePlayerActivityReport deletes a player activity report by its ID
|
||||||
|
func (s *Store) DeletePlayerActivityReport(ctx context.Context, id int64) error {
|
||||||
|
err := s.queries.DeletePlayerActivityReport(ctx, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||||
|
|
@ -75,22 +74,22 @@ type App struct {
|
||||||
userSvc *user.Service
|
userSvc *user.Service
|
||||||
betSvc *bet.Service
|
betSvc *bet.Service
|
||||||
virtualGameSvc virtualgameservice.VirtualGameService
|
virtualGameSvc virtualgameservice.VirtualGameService
|
||||||
reportSvc report.ReportService
|
// reportSvc report.ReportService
|
||||||
chapaSvc *chapa.Service
|
chapaSvc *chapa.Service
|
||||||
walletSvc *wallet.Service
|
walletSvc *wallet.Service
|
||||||
transactionSvc *transaction.Service
|
transactionSvc *transaction.Service
|
||||||
ticketSvc *ticket.Service
|
ticketSvc *ticket.Service
|
||||||
branchSvc *branch.Service
|
branchSvc *branch.Service
|
||||||
companySvc *company.Service
|
companySvc *company.Service
|
||||||
validator *customvalidator.CustomValidator
|
validator *customvalidator.CustomValidator
|
||||||
JwtConfig jwtutil.JwtConfig
|
JwtConfig jwtutil.JwtConfig
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
prematchSvc *odds.ServiceImpl
|
prematchSvc *odds.ServiceImpl
|
||||||
eventSvc *event.Service
|
eventSvc *event.Service
|
||||||
leagueSvc *league.Service
|
leagueSvc *league.Service
|
||||||
resultSvc *result.Service
|
resultSvc *result.Service
|
||||||
statSvc *stats.Service
|
statSvc *stats.Service
|
||||||
mongoLoggerSvc *zap.Logger
|
mongoLoggerSvc *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApp(
|
func NewApp(
|
||||||
|
|
@ -113,7 +112,7 @@ func NewApp(
|
||||||
userSvc *user.Service,
|
userSvc *user.Service,
|
||||||
ticketSvc *ticket.Service,
|
ticketSvc *ticket.Service,
|
||||||
betSvc *bet.Service,
|
betSvc *bet.Service,
|
||||||
reportSvc report.ReportService,
|
// reportSvc report.ReportService,
|
||||||
chapaSvc *chapa.Service,
|
chapaSvc *chapa.Service,
|
||||||
walletSvc *wallet.Service,
|
walletSvc *wallet.Service,
|
||||||
transactionSvc *transaction.Service,
|
transactionSvc *transaction.Service,
|
||||||
|
|
@ -166,15 +165,15 @@ func NewApp(
|
||||||
fiber: app,
|
fiber: app,
|
||||||
port: port,
|
port: port,
|
||||||
|
|
||||||
settingSvc: settingSvc,
|
settingSvc: settingSvc,
|
||||||
authSvc: authSvc,
|
authSvc: authSvc,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
JwtConfig: JwtConfig,
|
JwtConfig: JwtConfig,
|
||||||
userSvc: userSvc,
|
userSvc: userSvc,
|
||||||
ticketSvc: ticketSvc,
|
ticketSvc: ticketSvc,
|
||||||
betSvc: betSvc,
|
betSvc: betSvc,
|
||||||
reportSvc: reportSvc,
|
// reportSvc: reportSvc,
|
||||||
chapaSvc: chapaSvc,
|
chapaSvc: chapaSvc,
|
||||||
walletSvc: walletSvc,
|
walletSvc: walletSvc,
|
||||||
transactionSvc: transactionSvc,
|
transactionSvc: transactionSvc,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/raffle"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/santimpay"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||||
|
|
@ -44,23 +43,23 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
directDepositSvc *directdeposit.Service
|
directDepositSvc *directdeposit.Service
|
||||||
orchestrationSvc *orchestration.Service
|
orchestrationSvc *orchestration.Service
|
||||||
enetPulseSvc *enetpulse.Service
|
enetPulseSvc *enetpulse.Service
|
||||||
telebirrSvc *telebirr.TelebirrService
|
telebirrSvc *telebirr.TelebirrService
|
||||||
arifpaySvc *arifpay.ArifpayService
|
arifpaySvc *arifpay.ArifpayService
|
||||||
santimpaySvc *santimpay.SantimPayService
|
santimpaySvc *santimpay.SantimPayService
|
||||||
issueReportingSvc *issuereporting.Service
|
issueReportingSvc *issuereporting.Service
|
||||||
instSvc *institutions.Service
|
instSvc *institutions.Service
|
||||||
currSvc *currency.Service
|
currSvc *currency.Service
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
settingSvc *settings.Service
|
settingSvc *settings.Service
|
||||||
notificationSvc *notificationservice.Service
|
notificationSvc *notificationservice.Service
|
||||||
userSvc *user.Service
|
userSvc *user.Service
|
||||||
referralSvc *referralservice.Service
|
referralSvc *referralservice.Service
|
||||||
raffleSvc *raffle.Service
|
raffleSvc *raffle.Service
|
||||||
bonusSvc *bonus.Service
|
bonusSvc *bonus.Service
|
||||||
reportSvc report.ReportService
|
// reportSvc report.ReportService
|
||||||
chapaSvc *chapa.Service
|
chapaSvc *chapa.Service
|
||||||
walletSvc *wallet.Service
|
walletSvc *wallet.Service
|
||||||
transactionSvc *transaction.Service
|
transactionSvc *transaction.Service
|
||||||
|
|
@ -99,7 +98,7 @@ func New(
|
||||||
settingSvc *settings.Service,
|
settingSvc *settings.Service,
|
||||||
notificationSvc *notificationservice.Service,
|
notificationSvc *notificationservice.Service,
|
||||||
validator *customvalidator.CustomValidator,
|
validator *customvalidator.CustomValidator,
|
||||||
reportSvc report.ReportService,
|
// reportSvc report.ReportService,
|
||||||
chapaSvc *chapa.Service,
|
chapaSvc *chapa.Service,
|
||||||
walletSvc *wallet.Service,
|
walletSvc *wallet.Service,
|
||||||
referralSvc *referralservice.Service,
|
referralSvc *referralservice.Service,
|
||||||
|
|
@ -127,19 +126,19 @@ func New(
|
||||||
mongoLoggerSvc *zap.Logger,
|
mongoLoggerSvc *zap.Logger,
|
||||||
) *Handler {
|
) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
directDepositSvc: directDepositSvc,
|
directDepositSvc: directDepositSvc,
|
||||||
orchestrationSvc: orchestrationSvc,
|
orchestrationSvc: orchestrationSvc,
|
||||||
enetPulseSvc: enetPulseSvc,
|
enetPulseSvc: enetPulseSvc,
|
||||||
telebirrSvc: telebirrSvc,
|
telebirrSvc: telebirrSvc,
|
||||||
arifpaySvc: arifpaySvc,
|
arifpaySvc: arifpaySvc,
|
||||||
santimpaySvc: santimpaySvc,
|
santimpaySvc: santimpaySvc,
|
||||||
issueReportingSvc: issueReportingSvc,
|
issueReportingSvc: issueReportingSvc,
|
||||||
instSvc: instSvc,
|
instSvc: instSvc,
|
||||||
currSvc: currSvc,
|
currSvc: currSvc,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
settingSvc: settingSvc,
|
settingSvc: settingSvc,
|
||||||
notificationSvc: notificationSvc,
|
notificationSvc: notificationSvc,
|
||||||
reportSvc: reportSvc,
|
// reportSvc: reportSvc,
|
||||||
chapaSvc: chapaSvc,
|
chapaSvc: chapaSvc,
|
||||||
walletSvc: walletSvc,
|
walletSvc: walletSvc,
|
||||||
referralSvc: referralSvc,
|
referralSvc: referralSvc,
|
||||||
|
|
|
||||||
|
|
@ -1,481 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetDashboardReport returns a comprehensive dashboard report
|
|
||||||
// @Summary Get dashboard report
|
|
||||||
// @Description Returns a comprehensive dashboard report with key metrics
|
|
||||||
// @Tags Reports
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param company_id query int false "Company ID filter"
|
|
||||||
// @Param branch_id query int false "Branch ID filter"
|
|
||||||
// @Param user_id query int false "User ID filter"
|
|
||||||
// @Param start_time query string false "Start time filter (RFC3339 format)"
|
|
||||||
// @Param end_time query string false "End time filter (RFC3339 format)"
|
|
||||||
// @Param sport_id query string false "Sport ID filter"
|
|
||||||
// @Param status query int false "Status filter (0=Pending, 1=Win, 2=Loss, 3=Half, 4=Void, 5=Error)"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {object} domain.DashboardSummary
|
|
||||||
// @Failure 400 {object} domain.ErrorResponse
|
|
||||||
// @Failure 401 {object} domain.ErrorResponse
|
|
||||||
// @Failure 500 {object} domain.ErrorResponse
|
|
||||||
// @Router /api/v1/reports/dashboard [get]
|
|
||||||
func (h *Handler) GetDashboardReport(c *fiber.Ctx) error {
|
|
||||||
role := c.Locals("role").(domain.Role)
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// Parse query parameters
|
|
||||||
filter, err := parseReportFilter(c, role)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Invalid filter parameters",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get report data
|
|
||||||
summary, err := h.reportSvc.GetDashboardSummary(ctx, filter)
|
|
||||||
if err != nil {
|
|
||||||
h.logger.Error("failed to get dashboard report", "error", err)
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Failed to generate report",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
res := domain.ConvertDashboardSummaryToRes(summary)
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
||||||
Message: "Dashboard reports generated successfully",
|
|
||||||
Success: true,
|
|
||||||
StatusCode: 200,
|
|
||||||
Data: res,
|
|
||||||
})
|
|
||||||
|
|
||||||
// return c.Status(fiber.StatusOK).JSON(summary)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseReportFilter parses query parameters into ReportFilter
|
|
||||||
func parseReportFilter(c *fiber.Ctx, role domain.Role) (domain.ReportFilter, error) {
|
|
||||||
var filter domain.ReportFilter
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if c.Query("company_id") != "" && role == domain.RoleSuperAdmin {
|
|
||||||
|
|
||||||
companyID, err := strconv.ParseInt(c.Query("company_id"), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid company_id: %w", err)
|
|
||||||
}
|
|
||||||
filter.CompanyID = domain.ValidInt64{Value: companyID, Valid: true}
|
|
||||||
} else {
|
|
||||||
filter.CompanyID = c.Locals("company_id").(domain.ValidInt64)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("branch_id") != "" && role == domain.RoleSuperAdmin {
|
|
||||||
branchID, err := strconv.ParseInt(c.Query("branch_id"), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid branch_id: %w", err)
|
|
||||||
}
|
|
||||||
filter.BranchID = domain.ValidInt64{Value: branchID, Valid: true}
|
|
||||||
} else {
|
|
||||||
filter.BranchID = c.Locals("branch_id").(domain.ValidInt64)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("user_id") != "" {
|
|
||||||
userID, err := strconv.ParseInt(c.Query("user_id"), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid user_id: %w", err)
|
|
||||||
}
|
|
||||||
filter.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("start_time") != "" {
|
|
||||||
startTime, err := time.Parse(time.RFC3339, c.Query("start_time"))
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid start_time: %w", err)
|
|
||||||
}
|
|
||||||
filter.StartTime = domain.ValidTime{Value: startTime, Valid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("end_time") != "" {
|
|
||||||
endTime, err := time.Parse(time.RFC3339, c.Query("end_time"))
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid end_time: %w", err)
|
|
||||||
}
|
|
||||||
filter.EndTime = domain.ValidTime{Value: endTime, Valid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("sport_id") != "" {
|
|
||||||
filter.SportID = domain.ValidString{Value: c.Query("sport_id"), Valid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("status") != "" {
|
|
||||||
status, err := strconv.ParseInt(c.Query("status"), 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return domain.ReportFilter{}, fmt.Errorf("invalid status: %w", err)
|
|
||||||
}
|
|
||||||
filter.Status = domain.ValidOutcomeStatus{Value: domain.OutcomeStatus(status), Valid: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DownloadReportFile godoc
|
|
||||||
// @Summary Download a CSV report file
|
|
||||||
// @Description Downloads a generated report CSV file from the server
|
|
||||||
// @Tags Reports
|
|
||||||
// @Param filename path string true "Name of the report file to download (e.g., report_daily_2025-06-21.csv)"
|
|
||||||
// @Produce text/csv
|
|
||||||
// @Success 200 {file} file "CSV file will be downloaded"
|
|
||||||
// @Failure 400 {object} domain.ErrorResponse "Missing or invalid filename"
|
|
||||||
// @Failure 404 {object} domain.ErrorResponse "Report file not found"
|
|
||||||
// @Failure 500 {object} domain.ErrorResponse "Internal server error while serving the file"
|
|
||||||
// @Router /api/v1/report-files/download/{filename} [get]
|
|
||||||
func (h *Handler) DownloadReportFile(c *fiber.Ctx) error {
|
|
||||||
filename := c.Params("filename")
|
|
||||||
if filename == "" || strings.Contains(filename, "..") {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Invalid filename parameter",
|
|
||||||
Error: "filename is required and must not contain '..'",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
reportDir := "C:/Users/User/Desktop/reports"
|
|
||||||
|
|
||||||
// Ensure reports directory exists
|
|
||||||
if _, err := os.Stat(reportDir); os.IsNotExist(err) {
|
|
||||||
if err := os.MkdirAll(reportDir, os.ModePerm); err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Failed to create report directory",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath := fmt.Sprintf("%s/%s", reportDir, filename)
|
|
||||||
|
|
||||||
// Check if the report file exists
|
|
||||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
|
||||||
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Report file not found",
|
|
||||||
Error: "no such file",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set download headers
|
|
||||||
c.Set("Content-Type", "text/csv")
|
|
||||||
c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
|
|
||||||
|
|
||||||
// Serve the file
|
|
||||||
if err := c.SendFile(filePath); err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Failed to serve file",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListReportFiles godoc
|
|
||||||
// @Summary List available report CSV files
|
|
||||||
// @Description Returns a paginated list of generated report CSV files with search capability
|
|
||||||
// @Tags Reports
|
|
||||||
// @Produce json
|
|
||||||
// @Param search query string false "Search term to filter filenames"
|
|
||||||
// @Param page query int false "Page number (default: 1)" default(1)
|
|
||||||
// @Param limit query int false "Items per page (default: 20, max: 100)" default(20)
|
|
||||||
// @Success 200 {object} domain.PaginatedFileResponse "Paginated list of CSV report filenames"
|
|
||||||
// @Failure 400 {object} domain.ErrorResponse "Invalid pagination parameters"
|
|
||||||
// @Failure 500 {object} domain.ErrorResponse "Failed to read report directory"
|
|
||||||
// @Router /api/v1/report-files/list [get]
|
|
||||||
func (h *Handler) ListReportFiles(c *fiber.Ctx) error {
|
|
||||||
reportDir := "C:/Users/User/Desktop/reports"
|
|
||||||
searchTerm := c.Query("search")
|
|
||||||
page := c.QueryInt("page", 1)
|
|
||||||
limit := c.QueryInt("limit", 20)
|
|
||||||
|
|
||||||
// Validate pagination parameters
|
|
||||||
if page < 1 {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Invalid page number",
|
|
||||||
Error: "Page must be greater than 0",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if limit < 1 || limit > 100 {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Invalid limit value",
|
|
||||||
Error: "Limit must be between 1 and 100",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the reports directory if it doesn't exist
|
|
||||||
if _, err := os.Stat(reportDir); os.IsNotExist(err) {
|
|
||||||
if err := os.MkdirAll(reportDir, os.ModePerm); err != nil {
|
|
||||||
h.mongoLoggerSvc.Error("failed to create report directory",
|
|
||||||
zap.Int64("status_code", fiber.StatusInternalServerError),
|
|
||||||
zap.Error(err),
|
|
||||||
zap.Time("timestamp", time.Now()),
|
|
||||||
)
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Failed to create report directory",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := os.ReadDir(reportDir)
|
|
||||||
if err != nil {
|
|
||||||
h.mongoLoggerSvc.Error("failed to read report directory",
|
|
||||||
zap.Int64("status_code", fiber.StatusInternalServerError),
|
|
||||||
zap.Error(err),
|
|
||||||
zap.Time("timestamp", time.Now()),
|
|
||||||
)
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
||||||
Message: "Failed to read report directory",
|
|
||||||
Error: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var allFiles []string
|
|
||||||
for _, file := range files {
|
|
||||||
if !file.IsDir() && strings.HasSuffix(file.Name(), ".csv") {
|
|
||||||
// Apply search filter if provided
|
|
||||||
if searchTerm == "" || strings.Contains(strings.ToLower(file.Name()), strings.ToLower(searchTerm)) {
|
|
||||||
allFiles = append(allFiles, file.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort files by name (descending to show newest first)
|
|
||||||
sort.Slice(allFiles, func(i, j int) bool {
|
|
||||||
return allFiles[i] > allFiles[j]
|
|
||||||
})
|
|
||||||
|
|
||||||
// Calculate pagination values
|
|
||||||
total := len(allFiles)
|
|
||||||
startIdx := (page - 1) * limit
|
|
||||||
endIdx := startIdx + limit
|
|
||||||
|
|
||||||
// Adjust end index if it exceeds the slice length
|
|
||||||
if endIdx > total {
|
|
||||||
endIdx = total
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle case where start index is beyond available items
|
|
||||||
if startIdx >= total {
|
|
||||||
return c.Status(fiber.StatusOK).JSON(domain.PaginatedFileResponse{
|
|
||||||
Response: domain.Response{
|
|
||||||
StatusCode: fiber.StatusOK,
|
|
||||||
Message: "No files found for the requested page",
|
|
||||||
Success: true,
|
|
||||||
},
|
|
||||||
Data: []string{},
|
|
||||||
Pagination: domain.Pagination{
|
|
||||||
Total: total,
|
|
||||||
TotalPages: int(math.Ceil(float64(total) / float64(limit))),
|
|
||||||
CurrentPage: page,
|
|
||||||
Limit: limit,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
paginatedFiles := allFiles[startIdx:endIdx]
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(domain.PaginatedFileResponse{
|
|
||||||
Response: domain.Response{
|
|
||||||
StatusCode: fiber.StatusOK,
|
|
||||||
Message: "Report files retrieved successfully",
|
|
||||||
Success: true,
|
|
||||||
},
|
|
||||||
Data: paginatedFiles,
|
|
||||||
Pagination: domain.Pagination{
|
|
||||||
Total: total,
|
|
||||||
TotalPages: int(math.Ceil(float64(total) / float64(limit))),
|
|
||||||
CurrentPage: page,
|
|
||||||
Limit: limit,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) CreateReportRequest(c *fiber.Ctx) error {
|
|
||||||
userID := c.Locals("user_id").(int64)
|
|
||||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
|
||||||
|
|
||||||
var req domain.CreateReportRequestReq
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
|
||||||
h.BadRequestLogger().Error(
|
|
||||||
"Failed to parse CreateReportRequestReq",
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request:", err.Error())
|
|
||||||
}
|
|
||||||
valErrs, ok := h.validator.Validate(c, req)
|
|
||||||
if !ok {
|
|
||||||
var errMsg string
|
|
||||||
for field, msg := range valErrs {
|
|
||||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
|
||||||
}
|
|
||||||
h.BadRequestLogger().Error(
|
|
||||||
"Failed to validate CreateReportRequestReq",
|
|
||||||
zap.String("errMsg", errMsg),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
request, err := h.reportSvc.CreateReportRequest(c.Context(), domain.CreateReportRequest{
|
|
||||||
CompanyID: companyID,
|
|
||||||
RequestedBy: domain.ValidInt64{
|
|
||||||
Value: userID,
|
|
||||||
Valid: true,
|
|
||||||
},
|
|
||||||
Type: domain.ReportRequestType(req.Type),
|
|
||||||
Metadata: req.Metadata,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
h.InternalServerErrorLogger().Error("Failed to create report request", zap.Error(err))
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
res := domain.ConvertReportRequest(request)
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Report Request has been created", res, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) GetAllReportRequests(c *fiber.Ctx) error {
|
|
||||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
|
||||||
|
|
||||||
page := c.QueryInt("page", 1)
|
|
||||||
pageSize := c.QueryInt("page_size", 10)
|
|
||||||
limit := domain.ValidInt32{
|
|
||||||
Value: int32(pageSize),
|
|
||||||
Valid: true,
|
|
||||||
}
|
|
||||||
offset := domain.ValidInt32{
|
|
||||||
Value: int32(page - 1),
|
|
||||||
Valid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
statusQuery := c.Query("status")
|
|
||||||
var reportStatus domain.ValidReportRequestStatus
|
|
||||||
if statusQuery != "" {
|
|
||||||
reportStatusParsed, err := domain.ParseReportRequestStatus(statusQuery)
|
|
||||||
if err != nil {
|
|
||||||
h.BadRequestLogger().Error("Failed to parse statusQuery",
|
|
||||||
zap.String("status", statusQuery),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid report status")
|
|
||||||
}
|
|
||||||
reportStatus = domain.ValidReportRequestStatus{
|
|
||||||
Value: reportStatusParsed,
|
|
||||||
Valid: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typeQuery := c.Query("type")
|
|
||||||
var reportType domain.ValidReportRequestType
|
|
||||||
if typeQuery != "" {
|
|
||||||
reportTypeParsed, err := domain.ParseReportRequestType(typeQuery)
|
|
||||||
if err != nil {
|
|
||||||
h.BadRequestLogger().Error("Failed to parse typeQuery",
|
|
||||||
zap.String("type", typeQuery),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid report type")
|
|
||||||
}
|
|
||||||
reportType = domain.ValidReportRequestType{
|
|
||||||
Value: reportTypeParsed,
|
|
||||||
Valid: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
requesterQuery := c.Query("requester")
|
|
||||||
var requestedBy domain.ValidInt64
|
|
||||||
if requesterQuery != "" {
|
|
||||||
parsedRequestedBy, err := strconv.ParseInt(requesterQuery, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
h.BadRequestLogger().Error("Failed to parse requester",
|
|
||||||
zap.String("requester", requesterQuery),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid report requester")
|
|
||||||
}
|
|
||||||
requestedBy = domain.ValidInt64{
|
|
||||||
Value: parsedRequestedBy,
|
|
||||||
Valid: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
requests, total, err := h.reportSvc.GetAllReportRequests(c.Context(), domain.ReportRequestFilter{
|
|
||||||
CompanyID: companyID,
|
|
||||||
Limit: limit,
|
|
||||||
Offset: offset,
|
|
||||||
Status: reportStatus,
|
|
||||||
Type: reportType,
|
|
||||||
RequestedBy: requestedBy,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
h.InternalServerErrorLogger().Error("Failed to retrieve all report requests",
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
res := domain.ConvertReportRequestDetailList(requests)
|
|
||||||
|
|
||||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "All Report Requests successfully retrieved", res, nil, page, int(total))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) DownloadReportByID(c *fiber.Ctx) error {
|
|
||||||
requestID := c.Params("id")
|
|
||||||
id, err := strconv.ParseInt(requestID, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
h.BadRequestLogger().Info("Invalid report request ID",
|
|
||||||
zap.String("requestID", requestID),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := h.reportSvc.CheckAndFetchReportFile(c.Context(), id)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
h.InternalServerErrorLogger().Error("Failed to check and fetch report file",
|
|
||||||
zap.Error(err),
|
|
||||||
zap.String("requestID", requestID),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to check and fetch report file:%v", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set("Content-Type", "text/csv")
|
|
||||||
c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", file))
|
|
||||||
|
|
||||||
if err := c.SendFile(file); err != nil {
|
|
||||||
h.InternalServerErrorLogger().Error("Unable to download report file",
|
|
||||||
zap.Error(err),
|
|
||||||
zap.String("requestID", requestID),
|
|
||||||
)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Unable to download report file:%v", err.Error()))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -33,7 +33,7 @@ func (a *App) initAppRoutes() {
|
||||||
a.settingSvc,
|
a.settingSvc,
|
||||||
a.NotidicationStore,
|
a.NotidicationStore,
|
||||||
a.validator,
|
a.validator,
|
||||||
a.reportSvc,
|
// a.reportSvc,
|
||||||
a.chapaSvc,
|
a.chapaSvc,
|
||||||
a.walletSvc,
|
a.walletSvc,
|
||||||
a.referralSvc,
|
a.referralSvc,
|
||||||
|
|
@ -408,13 +408,13 @@ func (a *App) initAppRoutes() {
|
||||||
groupV1.Get("/currencies/convert", h.ConvertCurrency)
|
groupV1.Get("/currencies/convert", h.ConvertCurrency)
|
||||||
|
|
||||||
//Report Routes
|
//Report Routes
|
||||||
groupV1.Get("/reports/dashboard", a.authMiddleware, a.OnlyAdminAndAbove, h.GetDashboardReport)
|
// groupV1.Get("/reports/dashboard", a.authMiddleware, a.OnlyAdminAndAbove, h.GetDashboardReport)
|
||||||
groupV1.Get("/report-files/download/:filename", h.DownloadReportFile)
|
// groupV1.Get("/report-files/download/:filename", h.DownloadReportFile)
|
||||||
groupV1.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
// groupV1.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
||||||
|
|
||||||
groupV1.Post("/reports/requests", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateReportRequest)
|
// groupV1.Post("/reports/requests", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateReportRequest)
|
||||||
groupV1.Get("/reports/requests", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllReportRequests)
|
// groupV1.Get("/reports/requests", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllReportRequests)
|
||||||
groupV1.Get("/reports/download/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportByID)
|
// groupV1.Get("/reports/download/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportByID)
|
||||||
|
|
||||||
//Alea Play Virtual Game Routes
|
//Alea Play Virtual Game Routes
|
||||||
groupV1.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
groupV1.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user