fix: version on route, better logs, error display, cleaning up code
This commit is contained in:
parent
5821618d73
commit
c83130394b
|
|
@ -123,7 +123,7 @@ func main() {
|
|||
companySvc := company.NewService(store)
|
||||
leagueSvc := league.New(store)
|
||||
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
|
||||
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, *settingSvc, notificationSvc, logger, domain.MongoDBLogger)
|
||||
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, *companySvc, *settingSvc, notificationSvc, logger, domain.MongoDBLogger)
|
||||
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
|
||||
bonusSvc := bonus.NewService(store)
|
||||
referalRepo := repository.NewReferralRepository(store)
|
||||
|
|
|
|||
259
db/data/seed_data.sql
Normal file
259
db/data/seed_data.sql
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
BEGIN;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended_at,
|
||||
suspended
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'John',
|
||||
'Doe',
|
||||
'john.doe@example.com',
|
||||
NULL,
|
||||
crypt('password123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
2,
|
||||
10000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO customer_wallets (
|
||||
id,
|
||||
customer_id,
|
||||
regular_wallet_id,
|
||||
static_wallet_id
|
||||
)
|
||||
VALUES (1, 1, 1, 2);
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
2,
|
||||
'Test',
|
||||
'Admin',
|
||||
'test.admin@gmail.com',
|
||||
'0988554466',
|
||||
crypt('password123', gen_salt('bf'))::bytea,
|
||||
'admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
NULL,
|
||||
FALSE,
|
||||
1
|
||||
);
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended_at,
|
||||
suspended
|
||||
)
|
||||
VALUES (
|
||||
3,
|
||||
'Samuel',
|
||||
'Tariku',
|
||||
'cybersamt@gmail.com',
|
||||
'0911111111',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended_at,
|
||||
suspended
|
||||
)
|
||||
VALUES (
|
||||
4,
|
||||
'Kirubel',
|
||||
'Kibru',
|
||||
'kirubeljkl679 @gmail.com',
|
||||
'0911554486',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
INSERT INTO supported_operations (id, name, description)
|
||||
VALUES (1, 'SportBook', 'Sportbook operations'),
|
||||
(2, 'Virtual', 'Virtual operations');
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
3,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO companies (
|
||||
id,
|
||||
name,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage
|
||||
)
|
||||
values (
|
||||
1,
|
||||
'Test Company',
|
||||
2,
|
||||
3,
|
||||
0.1
|
||||
);
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
4,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO branches (
|
||||
id,
|
||||
name,
|
||||
location,
|
||||
wallet_id,
|
||||
branch_manager_id,
|
||||
company_id,
|
||||
is_self_owned,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
values (
|
||||
1,
|
||||
'Test Branch',
|
||||
'Addis Ababa',
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
COMMIT;
|
||||
|
|
@ -206,14 +206,16 @@ CREATE TABLE IF NOT EXISTS shop_deposits (
|
|||
CREATE TABLE IF NOT EXISTS branches (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
location VARCHAR(255) NOT NULL,
|
||||
location TEXT NOT NULL,
|
||||
profit_percent REAL NOt NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||
wallet_id BIGINT NOT NULL,
|
||||
branch_manager_id BIGINT NOT NULL,
|
||||
company_id BIGINT NOT NULL,
|
||||
is_self_owned BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(wallet_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS branch_operations (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
|
|
@ -228,6 +230,10 @@ CREATE TABLE IF NOT EXISTS branch_cashiers (
|
|||
branch_id BIGINT NOT NULL,
|
||||
UNIQUE(user_id, branch_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS branch_locations (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE events (
|
||||
id TEXT PRIMARY KEY,
|
||||
sport_id INT,
|
||||
|
|
@ -279,6 +285,8 @@ CREATE TABLE companies (
|
|||
name TEXT NOT NULL,
|
||||
admin_id BIGINT NOT NULL,
|
||||
wallet_id BIGINT NOT NULL,
|
||||
deducted_percentage REAL NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
|
@ -314,7 +322,7 @@ CREATE TABLE bonus (
|
|||
CREATE VIEW companies_details AS
|
||||
SELECT companies.*,
|
||||
wallets.balance,
|
||||
wallets.is_active,
|
||||
wallets.is_active as wallet_is_active,
|
||||
users.first_name AS admin_first_name,
|
||||
users.last_name AS admin_last_name,
|
||||
users.phone_number AS admin_phone_number
|
||||
|
|
@ -458,7 +466,8 @@ ADD CONSTRAINT fk_shop_deposit_transactions FOREIGN KEY (shop_transaction_id) RE
|
|||
ADD CONSTRAINT fk_shop_deposit_customers FOREIGN KEY (customer_id) REFERENCES users(id);
|
||||
ALTER TABLE branches
|
||||
ADD CONSTRAINT fk_branches_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id),
|
||||
ADD CONSTRAINT fk_branches_manager FOREIGN KEY (branch_manager_id) REFERENCES users(id);
|
||||
ADD CONSTRAINT fk_branches_manager FOREIGN KEY (branch_manager_id) REFERENCES users(id),
|
||||
ADD CONSTRAINT fk_branches_location FOREIGN KEY (location) REFERENCES branch_locations(key);
|
||||
ALTER TABLE branch_operations
|
||||
ADD CONSTRAINT fk_branch_operations_operations FOREIGN KEY (operation_id) REFERENCES supported_operations(id) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT fk_branch_operations_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
-- Settings Initial Data
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('max_number_of_outcomes', '30') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('bet_amount_limit', '100000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('daily_ticket_limit', '50') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('total_winnings_limit', '1000000') ON CONFLICT (key) DO
|
||||
VALUES ('max_number_of_outcomes', '30'),
|
||||
('bet_amount_limit', '100000'),
|
||||
('daily_ticket_limit', '50'),
|
||||
('total_winnings_limit', '1000000'),
|
||||
('amount_for_bet_referral', '1000000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
76
db/migrations/000009_location_data.up.sql
Normal file
76
db/migrations/000009_location_data.up.sql
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
-- Locations Initial Data
|
||||
INSERT INTO branch_locations (key, value)
|
||||
VALUES ('addis_ababa', 'Addis Ababa'),
|
||||
('dire_dawa', 'Dire Dawa'),
|
||||
('mekelle', 'Mekelle'),
|
||||
('adama', 'Adama'),
|
||||
('awassa', 'Awassa'),
|
||||
('bahir_dar', 'Bahir Dar'),
|
||||
('gonder', 'Gonder'),
|
||||
('dessie', 'Dessie'),
|
||||
('jimma', 'Jimma'),
|
||||
('jijiga', 'Jijiga'),
|
||||
('shashamane', 'Shashamane'),
|
||||
('bishoftu', 'Bishoftu'),
|
||||
('sodo', 'Sodo'),
|
||||
('arba_minch', 'Arba Minch'),
|
||||
('hosaena', 'Hosaena'),
|
||||
('harar', 'Harar'),
|
||||
('dilla', 'Dilla'),
|
||||
('nekemte', 'Nekemte'),
|
||||
('debre_birhan', 'Debre Birhan'),
|
||||
('asella', 'Asella'),
|
||||
('debre_markos', 'Debre Markos'),
|
||||
('kombolcha', 'Kombolcha'),
|
||||
('debre_tabor', 'Debre Tabor'),
|
||||
('adigrat', 'Adigrat'),
|
||||
('areka', 'Areka'),
|
||||
('weldiya', 'Weldiya'),
|
||||
('sebeta', 'Sebeta'),
|
||||
('burayu', 'Burayu'),
|
||||
('shire', 'Shire'),
|
||||
('ambo', 'Ambo'),
|
||||
('arsi_negele', 'Arsi Negele'),
|
||||
('aksum', 'Aksum'),
|
||||
('gambela', 'Gambela'),
|
||||
('bale_robe', 'Bale Robe'),
|
||||
('butajira', 'Butajira'),
|
||||
('batu', 'Batu'),
|
||||
('boditi', 'Boditi'),
|
||||
('adwa', 'Adwa'),
|
||||
('yirgalem', 'Yirgalem'),
|
||||
('waliso', 'Waliso'),
|
||||
('welkite', 'Welkite'),
|
||||
('gode', 'Gode'),
|
||||
('meki', 'Meki'),
|
||||
('negele_borana', 'Negele Borana'),
|
||||
('alaba_kulito', 'Alaba Kulito'),
|
||||
('alamata 14,', 'Alamata 14,'),
|
||||
('030', '030'),
|
||||
('chiro', 'Chiro'),
|
||||
('tepi', 'Tepi'),
|
||||
('durame', 'Durame'),
|
||||
('goba', 'Goba'),
|
||||
('assosa', 'Assosa'),
|
||||
('gimbi', 'Gimbi'),
|
||||
('wukro', 'Wukro'),
|
||||
('haramaya', 'Haramaya'),
|
||||
('mizan_teferi', 'Mizan Teferi'),
|
||||
('sawla', 'Sawla'),
|
||||
('mojo', 'Mojo'),
|
||||
('dembi_dolo', 'Dembi Dolo'),
|
||||
('aleta_wendo', 'Aleta Wendo'),
|
||||
('metu', 'Metu'),
|
||||
('mota', 'Mota'),
|
||||
('fiche', 'Fiche'),
|
||||
('finote_selam', 'Finote Selam'),
|
||||
('bule_hora_town', 'Bule Hora Town'),
|
||||
('bonga', 'Bonga'),
|
||||
('kobo', 'Kobo'),
|
||||
('jinka', 'Jinka'),
|
||||
('dangila', 'Dangila'),
|
||||
('degehabur', 'Degehabur'),
|
||||
('bedessa', 'Bedessa'),
|
||||
('agaro', 'Agaro') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
134
db/query/bet_stat.sql
Normal file
134
db/query/bet_stat.sql
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
-- name: GetBetSummary :one
|
||||
SELECT SUM(amount) as total_stakes,
|
||||
COUNT(*) as total_bets,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 0 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as active_bets,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_wins,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 2 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_losses,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN amount * total_odds
|
||||
ELSE 0
|
||||
END
|
||||
) as win_balance
|
||||
FROM bets
|
||||
wHERE (
|
||||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < sqlc.narg('created_after')
|
||||
OR sqlc.narg('created_after') IS NULL
|
||||
);
|
||||
-- name: GetBetStats :many
|
||||
SELECT DATE(created_at) as date,
|
||||
COUNT(*) as total_bets,
|
||||
SUM(amount) as total_stakes,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_wins,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN amount * total_odds
|
||||
ELSE 0
|
||||
END
|
||||
) as total_payouts,
|
||||
AVG(total_odds) as average_odds
|
||||
FROM bets
|
||||
wHERE (
|
||||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
is_shop_bet = sqlc.narg('is_shop_bet')
|
||||
OR sqlc.narg('is_shop_bet') IS NULL
|
||||
)
|
||||
AND (
|
||||
cashed_out = sqlc.narg('cashed_out')
|
||||
OR sqlc.narg('cashed_out') IS NULL
|
||||
)
|
||||
AND (
|
||||
full_name ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR phone_number ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR sqlc.narg('query') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < sqlc.narg('created_after')
|
||||
OR sqlc.narg('created_after') IS NULL
|
||||
)
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY DATE(created_at);
|
||||
-- name: GetTotalBetsMadeInRange :one
|
||||
SELECT COUNT(*) AS total_bets
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to');
|
||||
-- name: GetTotalCashMadeInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_made
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to');
|
||||
-- name: GetTotalCashOutInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_out
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||
AND cashed_out = true;
|
||||
-- name: GetTotalCashBacksInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_backs
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||
AND status = 5;
|
||||
-- name: GetMarketPopularity :one
|
||||
WITH market_counts AS (
|
||||
SELECT DATE(b.created_at) as date,
|
||||
bo.market_name,
|
||||
COUNT(*) as bet_count,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(b.created_at)
|
||||
ORDER BY COUNT(*) DESC
|
||||
) as rank
|
||||
FROM bets b
|
||||
JOIN bet_outcomes bo ON b.id = bo.bet_id
|
||||
WHERE bo.market_name IS NOT NULL
|
||||
AND (
|
||||
user_id = sqlc.narg('user_id')
|
||||
OR sqlc.narg('user_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < sqlc.narg('created_after')
|
||||
OR sqlc.narg('created_after') IS NULL
|
||||
)
|
||||
GROUP BY DATE(b.created_at),
|
||||
bo.market_name
|
||||
)
|
||||
SELECT date,
|
||||
market_name
|
||||
FROM market_counts
|
||||
WHERE rank = 1;
|
||||
|
|
@ -2,9 +2,10 @@
|
|||
INSERT INTO companies (
|
||||
name,
|
||||
admin_id,
|
||||
wallet_id
|
||||
wallet_id,
|
||||
deducted_percentage
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
-- name: GetAllCompanies :many
|
||||
SELECT *
|
||||
|
|
@ -36,6 +37,11 @@ WHERE name ILIKE '%' || $1 || '%';
|
|||
UPDATE companies
|
||||
SET name = COALESCE(sqlc.narg(name), name),
|
||||
admin_id = COALESCE(sqlc.narg(admin_id), admin_id),
|
||||
is_active = COALESCE(sqlc.narg(is_active), is_active),
|
||||
deducted_percentage = COALESCE(
|
||||
sqlc.narg(deducted_percentage),
|
||||
deducted_percentage
|
||||
),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
|
|
|||
|
|
@ -168,6 +168,10 @@ WHERE is_live = false
|
|||
AND (
|
||||
leagues.country_code = sqlc.narg('country_code')
|
||||
OR sqlc.narg('country_code') IS NULL
|
||||
)
|
||||
AND (
|
||||
flagged = sqlc.narg('flagged')
|
||||
OR sqlc.narg('flagged') IS NULL
|
||||
);
|
||||
-- name: GetPaginatedUpcomingEvents :many
|
||||
SELECT events.*,
|
||||
|
|
@ -197,6 +201,10 @@ WHERE start_time > now()
|
|||
leagues.country_code = sqlc.narg('country_code')
|
||||
OR sqlc.narg('country_code') IS NULL
|
||||
)
|
||||
AND (
|
||||
flagged = sqlc.narg('flagged')
|
||||
OR sqlc.narg('flagged') IS NULL
|
||||
)
|
||||
ORDER BY start_time ASC
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
-- name: GetUpcomingByID :one
|
||||
|
|
|
|||
|
|
@ -1,21 +1,4 @@
|
|||
-- name: GetTotalBetsMadeInRange :one
|
||||
SELECT COUNT(*) AS total_bets
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to');
|
||||
-- name: GetTotalCashMadeInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_made
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to');
|
||||
-- name: GetTotalCashOutInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_out
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||
AND cashed_out = true;
|
||||
-- name: GetTotalCashBacksInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_backs
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||
AND status = 5;
|
||||
|
||||
-- name: GetCompanyWiseReport :many
|
||||
SELECT b.company_id,
|
||||
c.name AS company_name,
|
||||
|
|
|
|||
|
|
@ -11,3 +11,25 @@ VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
|||
UPDATE
|
||||
SET value = EXCLUDED.value
|
||||
RETURNING *;
|
||||
|
||||
-- name: SetInitialData :exec
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('max_number_of_outcomes', '30') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('bet_amount_limit', '100000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('daily_ticket_limit', '50') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('total_winnings_limit', '1000000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('amount_for_bet_referral', '1000000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
9010
docs/docs.go
9010
docs/docs.go
File diff suppressed because it is too large
Load Diff
9010
docs/swagger.json
9010
docs/swagger.json
File diff suppressed because it is too large
Load Diff
5994
docs/swagger.yaml
5994
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
307
gen/db/bet_stat.sql.go
Normal file
307
gen/db/bet_stat.sql.go
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
// source: bet_stat.sql
|
||||
|
||||
package dbgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const GetBetStats = `-- name: GetBetStats :many
|
||||
SELECT DATE(created_at) as date,
|
||||
COUNT(*) as total_bets,
|
||||
SUM(amount) as total_stakes,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_wins,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN amount * total_odds
|
||||
ELSE 0
|
||||
END
|
||||
) as total_payouts,
|
||||
AVG(total_odds) as average_odds
|
||||
FROM bets
|
||||
wHERE (
|
||||
user_id = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
is_shop_bet = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
cashed_out = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
full_name ILIKE '%' || $4 || '%'
|
||||
OR phone_number ILIKE '%' || $4 || '%'
|
||||
OR $4 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $5
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY DATE(created_at)
|
||||
`
|
||||
|
||||
type GetBetStatsParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
IsShopBet pgtype.Bool `json:"is_shop_bet"`
|
||||
CashedOut pgtype.Bool `json:"cashed_out"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
||||
type GetBetStatsRow struct {
|
||||
Date pgtype.Date `json:"date"`
|
||||
TotalBets int64 `json:"total_bets"`
|
||||
TotalStakes int64 `json:"total_stakes"`
|
||||
TotalWins int64 `json:"total_wins"`
|
||||
TotalPayouts int64 `json:"total_payouts"`
|
||||
AverageOdds float64 `json:"average_odds"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBetStats(ctx context.Context, arg GetBetStatsParams) ([]GetBetStatsRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetBetStats,
|
||||
arg.UserID,
|
||||
arg.IsShopBet,
|
||||
arg.CashedOut,
|
||||
arg.Query,
|
||||
arg.CreatedBefore,
|
||||
arg.CreatedAfter,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetBetStatsRow
|
||||
for rows.Next() {
|
||||
var i GetBetStatsRow
|
||||
if err := rows.Scan(
|
||||
&i.Date,
|
||||
&i.TotalBets,
|
||||
&i.TotalStakes,
|
||||
&i.TotalWins,
|
||||
&i.TotalPayouts,
|
||||
&i.AverageOdds,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const GetBetSummary = `-- name: GetBetSummary :one
|
||||
SELECT SUM(amount) as total_stakes,
|
||||
COUNT(*) as total_bets,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 0 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as active_bets,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_wins,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 2 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) as total_losses,
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 1 THEN amount * total_odds
|
||||
ELSE 0
|
||||
END
|
||||
) as win_balance
|
||||
FROM bets
|
||||
wHERE (
|
||||
user_id = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetBetSummaryParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
||||
type GetBetSummaryRow struct {
|
||||
TotalStakes int64 `json:"total_stakes"`
|
||||
TotalBets int64 `json:"total_bets"`
|
||||
ActiveBets int64 `json:"active_bets"`
|
||||
TotalWins int64 `json:"total_wins"`
|
||||
TotalLosses int64 `json:"total_losses"`
|
||||
WinBalance int64 `json:"win_balance"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBetSummary(ctx context.Context, arg GetBetSummaryParams) (GetBetSummaryRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetBetSummary, arg.UserID, arg.CreatedBefore, arg.CreatedAfter)
|
||||
var i GetBetSummaryRow
|
||||
err := row.Scan(
|
||||
&i.TotalStakes,
|
||||
&i.TotalBets,
|
||||
&i.ActiveBets,
|
||||
&i.TotalWins,
|
||||
&i.TotalLosses,
|
||||
&i.WinBalance,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetMarketPopularity = `-- name: GetMarketPopularity :one
|
||||
WITH market_counts AS (
|
||||
SELECT DATE(b.created_at) as date,
|
||||
bo.market_name,
|
||||
COUNT(*) as bet_count,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(b.created_at)
|
||||
ORDER BY COUNT(*) DESC
|
||||
) as rank
|
||||
FROM bets b
|
||||
JOIN bet_outcomes bo ON b.id = bo.bet_id
|
||||
WHERE bo.market_name IS NOT NULL
|
||||
AND (
|
||||
user_id = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
GROUP BY DATE(b.created_at),
|
||||
bo.market_name
|
||||
)
|
||||
SELECT date,
|
||||
market_name
|
||||
FROM market_counts
|
||||
WHERE rank = 1
|
||||
`
|
||||
|
||||
type GetMarketPopularityParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
||||
type GetMarketPopularityRow struct {
|
||||
Date pgtype.Date `json:"date"`
|
||||
MarketName string `json:"market_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetMarketPopularity(ctx context.Context, arg GetMarketPopularityParams) (GetMarketPopularityRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetMarketPopularity, arg.UserID, arg.CreatedBefore, arg.CreatedAfter)
|
||||
var i GetMarketPopularityRow
|
||||
err := row.Scan(&i.Date, &i.MarketName)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetTotalBetsMadeInRange = `-- name: GetTotalBetsMadeInRange :one
|
||||
SELECT COUNT(*) AS total_bets
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
`
|
||||
|
||||
type GetTotalBetsMadeInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalBetsMadeInRange(ctx context.Context, arg GetTotalBetsMadeInRangeParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalBetsMadeInRange, arg.From, arg.To)
|
||||
var total_bets int64
|
||||
err := row.Scan(&total_bets)
|
||||
return total_bets, err
|
||||
}
|
||||
|
||||
const GetTotalCashBacksInRange = `-- name: GetTotalCashBacksInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_backs
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
AND status = 5
|
||||
`
|
||||
|
||||
type GetTotalCashBacksInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashBacksInRange(ctx context.Context, arg GetTotalCashBacksInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashBacksInRange, arg.From, arg.To)
|
||||
var total_cash_backs interface{}
|
||||
err := row.Scan(&total_cash_backs)
|
||||
return total_cash_backs, err
|
||||
}
|
||||
|
||||
const GetTotalCashMadeInRange = `-- name: GetTotalCashMadeInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_made
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
`
|
||||
|
||||
type GetTotalCashMadeInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashMadeInRange(ctx context.Context, arg GetTotalCashMadeInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashMadeInRange, arg.From, arg.To)
|
||||
var total_cash_made interface{}
|
||||
err := row.Scan(&total_cash_made)
|
||||
return total_cash_made, err
|
||||
}
|
||||
|
||||
const GetTotalCashOutInRange = `-- name: GetTotalCashOutInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_out
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
AND cashed_out = true
|
||||
`
|
||||
|
||||
type GetTotalCashOutInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashOutInRange(ctx context.Context, arg GetTotalCashOutInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashOutInRange, arg.From, arg.To)
|
||||
var total_cash_out interface{}
|
||||
err := row.Scan(&total_cash_out)
|
||||
return total_cash_out, err
|
||||
}
|
||||
|
|
@ -15,26 +15,35 @@ const CreateCompany = `-- name: CreateCompany :one
|
|||
INSERT INTO companies (
|
||||
name,
|
||||
admin_id,
|
||||
wallet_id
|
||||
wallet_id,
|
||||
deducted_percentage
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, name, admin_id, wallet_id, created_at, updated_at
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, name, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateCompanyParams struct {
|
||||
Name string `json:"name"`
|
||||
AdminID int64 `json:"admin_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCompany(ctx context.Context, arg CreateCompanyParams) (Company, error) {
|
||||
row := q.db.QueryRow(ctx, CreateCompany, arg.Name, arg.AdminID, arg.WalletID)
|
||||
row := q.db.QueryRow(ctx, CreateCompany,
|
||||
arg.Name,
|
||||
arg.AdminID,
|
||||
arg.WalletID,
|
||||
arg.DeductedPercentage,
|
||||
)
|
||||
var i Company
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
|
|
@ -52,7 +61,7 @@ func (q *Queries) DeleteCompany(ctx context.Context, id int64) error {
|
|||
}
|
||||
|
||||
const GetAllCompanies = `-- name: GetAllCompanies :many
|
||||
SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
SELECT id, name, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at, balance, wallet_is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
FROM companies_details
|
||||
WHERE (
|
||||
name ILIKE '%' || $1 || '%'
|
||||
|
|
@ -91,10 +100,12 @@ func (q *Queries) GetAllCompanies(ctx context.Context, arg GetAllCompaniesParams
|
|||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Balance,
|
||||
&i.IsActive,
|
||||
&i.WalletIsActive,
|
||||
&i.AdminFirstName,
|
||||
&i.AdminLastName,
|
||||
&i.AdminPhoneNumber,
|
||||
|
|
@ -110,7 +121,7 @@ func (q *Queries) GetAllCompanies(ctx context.Context, arg GetAllCompaniesParams
|
|||
}
|
||||
|
||||
const GetCompanyByID = `-- name: GetCompanyByID :one
|
||||
SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
SELECT id, name, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at, balance, wallet_is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
FROM companies_details
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -123,10 +134,12 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
|
|||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Balance,
|
||||
&i.IsActive,
|
||||
&i.WalletIsActive,
|
||||
&i.AdminFirstName,
|
||||
&i.AdminLastName,
|
||||
&i.AdminPhoneNumber,
|
||||
|
|
@ -135,7 +148,7 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
|
|||
}
|
||||
|
||||
const SearchCompanyByName = `-- name: SearchCompanyByName :many
|
||||
SELECT id, name, admin_id, wallet_id, created_at, updated_at, balance, is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
SELECT id, name, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at, balance, wallet_is_active, admin_first_name, admin_last_name, admin_phone_number
|
||||
FROM companies_details
|
||||
WHERE name ILIKE '%' || $1 || '%'
|
||||
`
|
||||
|
|
@ -154,10 +167,12 @@ func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text)
|
|||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Balance,
|
||||
&i.IsActive,
|
||||
&i.WalletIsActive,
|
||||
&i.AdminFirstName,
|
||||
&i.AdminLastName,
|
||||
&i.AdminPhoneNumber,
|
||||
|
|
@ -176,25 +191,40 @@ const UpdateCompany = `-- name: UpdateCompany :one
|
|||
UPDATE companies
|
||||
SET name = COALESCE($2, name),
|
||||
admin_id = COALESCE($3, admin_id),
|
||||
is_active = COALESCE($4, is_active),
|
||||
deducted_percentage = COALESCE(
|
||||
$5,
|
||||
deducted_percentage
|
||||
),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING id, name, admin_id, wallet_id, created_at, updated_at
|
||||
RETURNING id, name, admin_id, wallet_id, deducted_percentage, is_active, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateCompanyParams struct {
|
||||
ID int64 `json:"id"`
|
||||
Name pgtype.Text `json:"name"`
|
||||
AdminID pgtype.Int8 `json:"admin_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
DeductedPercentage pgtype.Float4 `json:"deducted_percentage"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCompany(ctx context.Context, arg UpdateCompanyParams) (Company, error) {
|
||||
row := q.db.QueryRow(ctx, UpdateCompany, arg.ID, arg.Name, arg.AdminID)
|
||||
row := q.db.QueryRow(ctx, UpdateCompany,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.AdminID,
|
||||
arg.IsActive,
|
||||
arg.DeductedPercentage,
|
||||
)
|
||||
var i Company
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
&i.DeductedPercentage,
|
||||
&i.IsActive,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -187,8 +187,12 @@ WHERE start_time > now()
|
|||
leagues.country_code = $5
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
flagged = $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
ORDER BY start_time ASC
|
||||
LIMIT $7 OFFSET $6
|
||||
LIMIT $8 OFFSET $7
|
||||
`
|
||||
|
||||
type GetPaginatedUpcomingEventsParams struct {
|
||||
|
|
@ -197,6 +201,7 @@ type GetPaginatedUpcomingEventsParams struct {
|
|||
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
||||
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
||||
CountryCode pgtype.Text `json:"country_code"`
|
||||
Flagged pgtype.Bool `json:"flagged"`
|
||||
Offset pgtype.Int4 `json:"offset"`
|
||||
Limit pgtype.Int4 `json:"limit"`
|
||||
}
|
||||
|
|
@ -235,6 +240,7 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
|
|||
arg.LastStartTime,
|
||||
arg.FirstStartTime,
|
||||
arg.CountryCode,
|
||||
arg.Flagged,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
|
|
@ -307,6 +313,10 @@ WHERE is_live = false
|
|||
leagues.country_code = $5
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
flagged = $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetTotalEventsParams struct {
|
||||
|
|
@ -315,6 +325,7 @@ type GetTotalEventsParams struct {
|
|||
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
||||
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
||||
CountryCode pgtype.Text `json:"country_code"`
|
||||
Flagged pgtype.Bool `json:"flagged"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams) (int64, error) {
|
||||
|
|
@ -324,6 +335,7 @@ func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams)
|
|||
arg.LastStartTime,
|
||||
arg.FirstStartTime,
|
||||
arg.CountryCode,
|
||||
arg.Flagged,
|
||||
)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
|
|
|
|||
|
|
@ -177,10 +177,12 @@ type CompaniesDetail struct {
|
|||
Name string `json:"name"`
|
||||
AdminID int64 `json:"admin_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
Balance int64 `json:"balance"`
|
||||
IsActive bool `json:"is_active"`
|
||||
WalletIsActive bool `json:"wallet_is_active"`
|
||||
AdminFirstName string `json:"admin_first_name"`
|
||||
AdminLastName string `json:"admin_last_name"`
|
||||
AdminPhoneNumber pgtype.Text `json:"admin_phone_number"`
|
||||
|
|
@ -191,6 +193,8 @@ type Company struct {
|
|||
Name string `json:"name"`
|
||||
AdminID int64 `json:"admin_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,77 +156,3 @@ func (q *Queries) GetCompanyWiseReport(ctx context.Context, arg GetCompanyWiseRe
|
|||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const GetTotalBetsMadeInRange = `-- name: GetTotalBetsMadeInRange :one
|
||||
SELECT COUNT(*) AS total_bets
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
`
|
||||
|
||||
type GetTotalBetsMadeInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalBetsMadeInRange(ctx context.Context, arg GetTotalBetsMadeInRangeParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalBetsMadeInRange, arg.From, arg.To)
|
||||
var total_bets int64
|
||||
err := row.Scan(&total_bets)
|
||||
return total_bets, err
|
||||
}
|
||||
|
||||
const GetTotalCashBacksInRange = `-- name: GetTotalCashBacksInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_backs
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
AND status = 5
|
||||
`
|
||||
|
||||
type GetTotalCashBacksInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashBacksInRange(ctx context.Context, arg GetTotalCashBacksInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashBacksInRange, arg.From, arg.To)
|
||||
var total_cash_backs interface{}
|
||||
err := row.Scan(&total_cash_backs)
|
||||
return total_cash_backs, err
|
||||
}
|
||||
|
||||
const GetTotalCashMadeInRange = `-- name: GetTotalCashMadeInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_made
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
`
|
||||
|
||||
type GetTotalCashMadeInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashMadeInRange(ctx context.Context, arg GetTotalCashMadeInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashMadeInRange, arg.From, arg.To)
|
||||
var total_cash_made interface{}
|
||||
err := row.Scan(&total_cash_made)
|
||||
return total_cash_made, err
|
||||
}
|
||||
|
||||
const GetTotalCashOutInRange = `-- name: GetTotalCashOutInRange :one
|
||||
SELECT COALESCE(SUM(amount), 0) AS total_cash_out
|
||||
FROM bets
|
||||
WHERE created_at BETWEEN $1 AND $2
|
||||
AND cashed_out = true
|
||||
`
|
||||
|
||||
type GetTotalCashOutInRangeParams struct {
|
||||
From pgtype.Timestamp `json:"from"`
|
||||
To pgtype.Timestamp `json:"to"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalCashOutInRange(ctx context.Context, arg GetTotalCashOutInRangeParams) (interface{}, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalCashOutInRange, arg.From, arg.To)
|
||||
var total_cash_out interface{}
|
||||
err := row.Scan(&total_cash_out)
|
||||
return total_cash_out, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ type CreateBetOutcomeReq struct {
|
|||
type CreateBetReq struct {
|
||||
Outcomes []CreateBetOutcomeReq `json:"outcomes"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
BranchID *int64 `json:"branch_id,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
type RandomBetReq struct {
|
||||
|
|
|
|||
|
|
@ -74,3 +74,98 @@ type CreateBranchOperation struct {
|
|||
BranchID int64
|
||||
OperationID int64
|
||||
}
|
||||
|
||||
type CreateBranchReq struct {
|
||||
Name string `json:"name" validate:"required,min=3,max=100" example:"4-kilo Branch"`
|
||||
Location string `json:"location" validate:"required,min=3,max=100" example:"Addis Ababa"`
|
||||
BranchManagerID int64 `json:"branch_manager_id" validate:"required,gt=0" example:"1"`
|
||||
CompanyID *int64 `json:"company_id,omitempty" example:"1"`
|
||||
IsSelfOwned *bool `json:"is_self_owned,omitempty" example:"false"`
|
||||
Operations []int64 `json:"operations" validate:"required,dive,gt=0"`
|
||||
}
|
||||
|
||||
type UpdateBranchReq struct {
|
||||
Name *string `json:"name,omitempty" example:"4-kilo Branch"`
|
||||
Location *string `json:"location,omitempty" example:"Addis Ababa"`
|
||||
BranchManagerID *int64 `json:"branch_manager_id,omitempty" example:"1"`
|
||||
CompanyID *int64 `json:"company_id,omitempty" example:"1"`
|
||||
IsSelfOwned *bool `json:"is_self_owned,omitempty" example:"false"`
|
||||
IsActive *bool `json:"is_active,omitempty" example:"false"`
|
||||
}
|
||||
|
||||
type CreateSupportedOperationReq struct {
|
||||
Name string `json:"name" example:"SportsBook"`
|
||||
Description string `json:"description" example:"Betting on sport events"`
|
||||
}
|
||||
|
||||
type SupportedOperationRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"SportsBook"`
|
||||
Description string `json:"description" example:"Betting on sport events"`
|
||||
}
|
||||
|
||||
type CreateBranchOperationReq struct {
|
||||
BranchID int64 `json:"branch_id" example:"1"`
|
||||
OperationID int64 `json:"operation_id" example:"1"`
|
||||
}
|
||||
|
||||
type BranchOperationRes struct {
|
||||
Name string `json:"name" example:"SportsBook"`
|
||||
Description string `json:"description" example:"Betting on sport events"`
|
||||
}
|
||||
|
||||
type BranchRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"4-kilo Branch"`
|
||||
Location string `json:"location" example:"Addis Ababa"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
BranchManagerID int64 `json:"branch_manager_id" example:"1"`
|
||||
CompanyID int64 `json:"company_id" example:"1"`
|
||||
IsSelfOwned bool `json:"is_self_owned" example:"false"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
}
|
||||
|
||||
type BranchDetailRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"4-kilo Branch"`
|
||||
Location string `json:"location" example:"Addis Ababa"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
BranchManagerID int64 `json:"branch_manager_id" example:"1"`
|
||||
CompanyID int64 `json:"company_id" example:"1"`
|
||||
IsSelfOwned bool `json:"is_self_owned" example:"false"`
|
||||
ManagerName string `json:"manager_name" example:"John Smith"`
|
||||
ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"`
|
||||
Balance float32 `json:"balance" example:"100.5"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
WalletIsActive bool `json:"is_wallet_active" example:"false"`
|
||||
}
|
||||
|
||||
func ConvertBranch(branch Branch) BranchRes {
|
||||
return BranchRes{
|
||||
ID: branch.ID,
|
||||
Name: branch.Name,
|
||||
Location: branch.Location,
|
||||
WalletID: branch.WalletID,
|
||||
BranchManagerID: branch.BranchManagerID,
|
||||
CompanyID: branch.CompanyID,
|
||||
IsSelfOwned: branch.IsSelfOwned,
|
||||
IsActive: branch.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertBranchDetail(branch BranchDetail) BranchDetailRes {
|
||||
return BranchDetailRes{
|
||||
ID: branch.ID,
|
||||
Name: branch.Name,
|
||||
Location: branch.Location,
|
||||
WalletID: branch.WalletID,
|
||||
BranchManagerID: branch.BranchManagerID,
|
||||
CompanyID: branch.CompanyID,
|
||||
IsSelfOwned: branch.IsSelfOwned,
|
||||
ManagerName: branch.ManagerName,
|
||||
ManagerPhoneNumber: branch.ManagerPhoneNumber,
|
||||
Balance: branch.Balance.Float32(),
|
||||
IsActive: branch.IsActive,
|
||||
WalletIsActive: branch.WalletIsActive,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ type ValidInt32 struct {
|
|||
Valid bool
|
||||
}
|
||||
|
||||
type ValidFloat32 struct {
|
||||
Value float32
|
||||
Valid bool
|
||||
}
|
||||
|
||||
type ValidString struct {
|
||||
Value string
|
||||
Valid bool
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
// Company represents the client that we will contract the services with
|
||||
// they are the ones that manage the branches and branch managers
|
||||
// they will have their own wallet that they will use to distribute to the branch wallets
|
||||
|
|
@ -8,6 +13,8 @@ type Company struct {
|
|||
Name string
|
||||
AdminID int64
|
||||
WalletID int64
|
||||
DeductedPercentage float32
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
type CompanyFilter struct {
|
||||
|
|
@ -27,16 +34,193 @@ type GetCompany struct {
|
|||
WalletID int64
|
||||
WalletBalance Currency
|
||||
IsWalletActive bool
|
||||
DeductedPercentage float32
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
type CreateCompany struct {
|
||||
Name string
|
||||
AdminID int64
|
||||
WalletID int64
|
||||
DeductedPercentage float32
|
||||
}
|
||||
|
||||
type UpdateCompany struct {
|
||||
ID int64
|
||||
Name *string
|
||||
AdminID *int64
|
||||
Name ValidString
|
||||
AdminID ValidInt64
|
||||
IsActive ValidBool
|
||||
DeductedPercentage ValidFloat32
|
||||
}
|
||||
|
||||
type CreateCompanyReq struct {
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
}
|
||||
type UpdateCompanyReq struct {
|
||||
Name *string `json:"name,omitempty" example:"CompanyName"`
|
||||
AdminID *int64 `json:"admin_id,omitempty" example:"1"`
|
||||
IsActive *bool `json:"is_active,omitempty" example:"true"`
|
||||
DeductedPercentage *float32 `json:"deducted_percentage,omitempty" example:"0.1" validate:"lt=1"`
|
||||
}
|
||||
|
||||
type CompanyRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage" example:"0.1"`
|
||||
IsActive bool `json:"is_active" example:"true"`
|
||||
}
|
||||
|
||||
type GetCompanyRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
WalletBalance float32 `json:"balance" example:"1"`
|
||||
WalletIsActive bool `json:"is_wallet_active" example:"false"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
DeductedPercentage float32 `json:"deducted_percentage" example:"0.1"`
|
||||
AdminFirstName string `json:"admin_first_name" example:"John"`
|
||||
AdminLastName string `json:"admin_last_name" example:"Doe"`
|
||||
AdminPhoneNumber string `json:"admin_phone_number" example:"1234567890"`
|
||||
}
|
||||
|
||||
func ConvertCompany(company Company) CompanyRes {
|
||||
return CompanyRes{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
IsActive: company.IsActive,
|
||||
DeductedPercentage: company.DeductedPercentage,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertGetCompany(company GetCompany) GetCompanyRes {
|
||||
return GetCompanyRes{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
WalletBalance: company.WalletBalance.Float32(),
|
||||
IsActive: company.IsActive,
|
||||
WalletIsActive: company.IsWalletActive,
|
||||
DeductedPercentage: company.DeductedPercentage,
|
||||
AdminFirstName: company.AdminFirstName,
|
||||
AdminLastName: company.AdminLastName,
|
||||
AdminPhoneNumber: company.AdminPhoneNumber,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertCreateCompany(company CreateCompany) dbgen.CreateCompanyParams {
|
||||
return dbgen.CreateCompanyParams{
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
DeductedPercentage: company.DeductedPercentage,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertDBCompany(dbCompany dbgen.Company) Company {
|
||||
return Company{
|
||||
ID: dbCompany.ID,
|
||||
Name: dbCompany.Name,
|
||||
AdminID: dbCompany.AdminID,
|
||||
WalletID: dbCompany.WalletID,
|
||||
DeductedPercentage: dbCompany.DeductedPercentage,
|
||||
IsActive: dbCompany.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertDBCompanyDetails(dbCompany dbgen.CompaniesDetail) GetCompany {
|
||||
return GetCompany{
|
||||
ID: dbCompany.ID,
|
||||
Name: dbCompany.Name,
|
||||
AdminID: dbCompany.AdminID,
|
||||
WalletID: dbCompany.WalletID,
|
||||
WalletBalance: Currency(dbCompany.Balance),
|
||||
IsWalletActive: dbCompany.WalletIsActive,
|
||||
AdminFirstName: dbCompany.AdminFirstName,
|
||||
AdminLastName: dbCompany.AdminLastName,
|
||||
AdminPhoneNumber: dbCompany.AdminPhoneNumber.String,
|
||||
DeductedPercentage: dbCompany.DeductedPercentage,
|
||||
IsActive: dbCompany.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertUpdateCompany(updateCompany UpdateCompany) dbgen.UpdateCompanyParams {
|
||||
newUpdateCompany := dbgen.UpdateCompanyParams{
|
||||
ID: updateCompany.ID,
|
||||
Name: pgtype.Text{
|
||||
String: updateCompany.Name.Value,
|
||||
Valid: updateCompany.Name.Valid,
|
||||
},
|
||||
AdminID: pgtype.Int8{
|
||||
Int64: updateCompany.AdminID.Value,
|
||||
Valid: updateCompany.AdminID.Valid,
|
||||
},
|
||||
IsActive: pgtype.Bool{
|
||||
Bool: updateCompany.IsActive.Value,
|
||||
Valid: updateCompany.IsActive.Valid,
|
||||
},
|
||||
DeductedPercentage: pgtype.Float4{
|
||||
Float32: updateCompany.DeductedPercentage.Value,
|
||||
Valid: updateCompany.DeductedPercentage.Valid,
|
||||
},
|
||||
}
|
||||
|
||||
return newUpdateCompany
|
||||
}
|
||||
|
||||
func ConvertUpdateCompanyReq(req UpdateCompanyReq) UpdateCompany {
|
||||
var updateCompany UpdateCompany
|
||||
|
||||
if req.Name != nil {
|
||||
updateCompany.Name = ValidString{
|
||||
Value: *req.Name,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
if req.AdminID != nil {
|
||||
updateCompany.AdminID = ValidInt64{
|
||||
Value: *req.AdminID,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
if req.IsActive != nil {
|
||||
updateCompany.IsActive = ValidBool{
|
||||
Value: *req.IsActive,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
if req.DeductedPercentage != nil {
|
||||
updateCompany.DeductedPercentage = ValidFloat32{
|
||||
Value: *req.DeductedPercentage,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
return updateCompany
|
||||
}
|
||||
|
||||
func ConvertGetAllCompaniesParams(filter CompanyFilter) dbgen.GetAllCompaniesParams {
|
||||
return dbgen.GetAllCompaniesParams{
|
||||
Query: pgtype.Text{
|
||||
String: filter.Query.Value,
|
||||
Valid: filter.Query.Valid,
|
||||
},
|
||||
CreatedBefore: pgtype.Timestamp{
|
||||
Time: filter.CreatedBefore.Value,
|
||||
Valid: filter.CreatedBefore.Valid,
|
||||
},
|
||||
CreatedAfter: pgtype.Timestamp{
|
||||
Time: filter.CreatedAfter.Value,
|
||||
Valid: filter.CreatedAfter.Valid,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,4 +128,5 @@ type EventFilter struct {
|
|||
Limit ValidInt64
|
||||
Offset ValidInt64
|
||||
MatchStatus ValidString // e.g., "upcoming", "in_play", "ended"
|
||||
Flagged ValidBool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Setting struct {
|
||||
Key string
|
||||
|
|
@ -19,4 +21,33 @@ type SettingList struct {
|
|||
BetAmountLimit Currency `json:"bet_amount_limit"`
|
||||
DailyTicketPerIP int64 `json:"daily_ticket_limit"`
|
||||
TotalWinningLimit Currency `json:"total_winning_limit"`
|
||||
AmountForBetReferral Currency `json:"amount_for_bet_referral"`
|
||||
}
|
||||
|
||||
type DBSettingList struct {
|
||||
MaxNumberOfOutcomes ValidInt64
|
||||
BetAmountLimit ValidInt64
|
||||
DailyTicketPerIP ValidInt64
|
||||
TotalWinningLimit ValidInt64
|
||||
AmountForBetReferral ValidInt64
|
||||
}
|
||||
|
||||
func ConvertInt64SettingsMap(dbSettingList *DBSettingList) map[string]*ValidInt64 {
|
||||
return map[string]*ValidInt64{
|
||||
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||
"bet_amount_limit": &dbSettingList.BetAmountLimit,
|
||||
"daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
||||
"total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
||||
"amount_for_bet_referral": &dbSettingList.AmountForBetReferral,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertDBSetting(dbSettingList DBSettingList) SettingList {
|
||||
return SettingList{
|
||||
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
||||
BetAmountLimit: Currency(dbSettingList.BetAmountLimit.Value),
|
||||
DailyTicketPerIP: dbSettingList.DailyTicketPerIP.Value,
|
||||
TotalWinningLimit: Currency(dbSettingList.TotalWinningLimit.Value),
|
||||
AmountForBetReferral: Currency(dbSettingList.AmountForBetReferral.Value),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,3 +187,7 @@ func ConvertShopTransactionDetail(transaction ShopTransactionDetail) ShopTransac
|
|||
|
||||
return newTransaction
|
||||
}
|
||||
|
||||
type UpdateTransactionVerifiedReq struct {
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
|||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
||||
query += fmt.Sprintf(" %suser_id = $%d", func() string {
|
||||
if len(args) == 0 {
|
||||
return " WHERE "
|
||||
}
|
||||
|
|
@ -480,21 +480,21 @@ func (s *Store) GetBetStats(ctx context.Context, filter domain.ReportFilter) ([]
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||
if len(args) == 0 {
|
||||
return " WHERE "
|
||||
}
|
||||
return " AND "
|
||||
}(), argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||
// if len(args) == 0 {
|
||||
// return " WHERE "
|
||||
// }
|
||||
// return " AND "
|
||||
// }(), argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
||||
if len(args) == 0 {
|
||||
|
|
@ -594,16 +594,16 @@ func (s *Store) GetSportPopularity(ctx context.Context, filter domain.ReportFilt
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
@ -684,16 +684,6 @@ func (s *Store) GetMarketPopularity(ctx context.Context, filter domain.ReportFil
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
@ -770,21 +760,21 @@ func (s *Store) GetExtremeValues(ctx context.Context, filter domain.ReportFilter
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||
if len(args) == 0 {
|
||||
return " WHERE "
|
||||
}
|
||||
return " AND "
|
||||
}(), argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||
// if len(args) == 0 {
|
||||
// return " WHERE "
|
||||
// }
|
||||
// return " AND "
|
||||
// }(), argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
||||
if len(args) == 0 {
|
||||
|
|
@ -880,16 +870,16 @@ func (s *Store) GetCustomerBetActivity(ctx context.Context, filter domain.Report
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
@ -975,16 +965,16 @@ func (s *Store) GetBranchBetActivity(ctx context.Context, filter domain.ReportFi
|
|||
argPos := 1
|
||||
|
||||
// Add filters if provided
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.StartTime.Valid {
|
||||
query += fmt.Sprintf(" AND created_at >= $%d", argPos)
|
||||
args = append(args, filter.StartTime.Value)
|
||||
|
|
@ -1059,16 +1049,16 @@ func (s *Store) GetSportBetActivity(ctx context.Context, filter domain.ReportFil
|
|||
args := []interface{}{}
|
||||
argPos := 1
|
||||
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
@ -1144,16 +1134,16 @@ func (s *Store) GetSportDetails(ctx context.Context, filter domain.ReportFilter)
|
|||
args := []interface{}{}
|
||||
argPos := 1
|
||||
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
@ -1220,16 +1210,16 @@ func (s *Store) GetSportMarketPopularity(ctx context.Context, filter domain.Repo
|
|||
args := []interface{}{}
|
||||
argPos := 1
|
||||
|
||||
if filter.CompanyID.Valid {
|
||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
args = append(args, filter.CompanyID.Value)
|
||||
argPos++
|
||||
}
|
||||
if filter.BranchID.Valid {
|
||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
args = append(args, filter.BranchID.Value)
|
||||
argPos++
|
||||
}
|
||||
// if filter.CompanyID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||
// args = append(args, filter.CompanyID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
// if filter.BranchID.Valid {
|
||||
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||
// args = append(args, filter.BranchID.Value)
|
||||
// argPos++
|
||||
// }
|
||||
if filter.UserID.Valid {
|
||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||
args = append(args, filter.UserID.Value)
|
||||
|
|
|
|||
|
|
@ -3,95 +3,28 @@ package repository
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func convertCreateCompany(company domain.CreateCompany) dbgen.CreateCompanyParams {
|
||||
return dbgen.CreateCompanyParams{
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
}
|
||||
}
|
||||
|
||||
func convertDBCompany(dbCompany dbgen.Company) domain.Company {
|
||||
return domain.Company{
|
||||
ID: dbCompany.ID,
|
||||
Name: dbCompany.Name,
|
||||
AdminID: dbCompany.AdminID,
|
||||
WalletID: dbCompany.WalletID,
|
||||
}
|
||||
}
|
||||
|
||||
func convertDBCompanyDetails(dbCompany dbgen.CompaniesDetail) domain.GetCompany {
|
||||
return domain.GetCompany{
|
||||
ID: dbCompany.ID,
|
||||
Name: dbCompany.Name,
|
||||
AdminID: dbCompany.AdminID,
|
||||
WalletID: dbCompany.WalletID,
|
||||
WalletBalance: domain.Currency(dbCompany.Balance),
|
||||
IsWalletActive: dbCompany.IsActive,
|
||||
AdminFirstName: dbCompany.AdminFirstName,
|
||||
AdminLastName: dbCompany.AdminLastName,
|
||||
AdminPhoneNumber: dbCompany.AdminPhoneNumber.String,
|
||||
}
|
||||
}
|
||||
|
||||
func convertUpdateCompany(updateCompany domain.UpdateCompany) dbgen.UpdateCompanyParams {
|
||||
var newUpdateCompany dbgen.UpdateCompanyParams
|
||||
|
||||
newUpdateCompany.ID = updateCompany.ID
|
||||
|
||||
if updateCompany.Name != nil {
|
||||
newUpdateCompany.Name = pgtype.Text{
|
||||
String: *updateCompany.Name,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
if updateCompany.AdminID != nil {
|
||||
newUpdateCompany.AdminID = pgtype.Int8{
|
||||
Int64: *updateCompany.AdminID,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
return newUpdateCompany
|
||||
}
|
||||
|
||||
func (s *Store) CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error) {
|
||||
dbCompany, err := s.queries.CreateCompany(ctx, convertCreateCompany(company))
|
||||
dbCompany, err := s.queries.CreateCompany(ctx, domain.ConvertCreateCompany(company))
|
||||
if err != nil {
|
||||
return domain.Company{}, err
|
||||
}
|
||||
return convertDBCompany(dbCompany), nil
|
||||
return domain.ConvertDBCompany(dbCompany), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error) {
|
||||
dbCompanies, err := s.queries.GetAllCompanies(ctx, dbgen.GetAllCompaniesParams{
|
||||
Query: pgtype.Text{
|
||||
String: filter.Query.Value,
|
||||
Valid: filter.Query.Valid,
|
||||
},
|
||||
CreatedBefore: pgtype.Timestamp{
|
||||
Time: filter.CreatedBefore.Value,
|
||||
Valid: filter.CreatedBefore.Valid,
|
||||
},
|
||||
CreatedAfter: pgtype.Timestamp{
|
||||
Time: filter.CreatedAfter.Value,
|
||||
Valid: filter.CreatedAfter.Valid,
|
||||
},
|
||||
})
|
||||
dbCompanies, err := s.queries.GetAllCompanies(ctx, domain.ConvertGetAllCompaniesParams(filter))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var companies []domain.GetCompany = make([]domain.GetCompany, 0, len(dbCompanies))
|
||||
for _, dbCompany := range dbCompanies {
|
||||
companies = append(companies, convertDBCompanyDetails(dbCompany))
|
||||
companies = append(companies, domain.ConvertDBCompanyDetails(dbCompany))
|
||||
}
|
||||
|
||||
return companies, nil
|
||||
|
|
@ -109,7 +42,7 @@ func (s *Store) SearchCompanyByName(ctx context.Context, name string) ([]domain.
|
|||
var companies []domain.GetCompany = make([]domain.GetCompany, 0, len(dbCompanies))
|
||||
|
||||
for _, dbCompany := range dbCompanies {
|
||||
companies = append(companies, convertDBCompanyDetails(dbCompany))
|
||||
companies = append(companies, domain.ConvertDBCompanyDetails(dbCompany))
|
||||
}
|
||||
return companies, nil
|
||||
}
|
||||
|
|
@ -120,17 +53,17 @@ func (s *Store) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany
|
|||
if err != nil {
|
||||
return domain.GetCompany{}, err
|
||||
}
|
||||
return convertDBCompanyDetails(dbCompany), nil
|
||||
return domain.ConvertDBCompanyDetails(dbCompany), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateCompany(ctx context.Context, company domain.UpdateCompany) (domain.Company, error) {
|
||||
dbCompany, err := s.queries.UpdateCompany(ctx, convertUpdateCompany(company))
|
||||
dbCompany, err := s.queries.UpdateCompany(ctx, domain.ConvertUpdateCompany(company))
|
||||
|
||||
if err != nil {
|
||||
return domain.Company{}, err
|
||||
}
|
||||
|
||||
return convertDBCompany(dbCompany), nil
|
||||
return domain.ConvertDBCompany(dbCompany), nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteCompany(ctx context.Context, id int64) error {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ func (s *Store) GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEven
|
|||
StartTime: e.StartTime.Time.UTC(),
|
||||
Source: e.Source.String,
|
||||
Status: domain.EventStatus(e.Status.String),
|
||||
Flagged: e.Flagged,
|
||||
}
|
||||
}
|
||||
return upcomingEvents, nil
|
||||
|
|
@ -121,6 +122,7 @@ func (s *Store) GetExpiredUpcomingEvents(ctx context.Context, filter domain.Even
|
|||
StartTime: e.StartTime.Time.UTC(),
|
||||
Source: e.Source.String,
|
||||
Status: domain.EventStatus(e.Status.String),
|
||||
Flagged: e.Flagged,
|
||||
}
|
||||
}
|
||||
return upcomingEvents, nil
|
||||
|
|
@ -157,6 +159,10 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
|||
String: filter.CountryCode.Value,
|
||||
Valid: filter.CountryCode.Valid,
|
||||
},
|
||||
Flagged: pgtype.Bool{
|
||||
Bool: filter.Flagged.Valid,
|
||||
Valid: filter.Flagged.Valid,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -180,7 +186,7 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
|||
StartTime: e.StartTime.Time.UTC(),
|
||||
Source: e.Source.String,
|
||||
Status: domain.EventStatus(e.Status.String),
|
||||
|
||||
Flagged: e.Flagged,
|
||||
}
|
||||
}
|
||||
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
|
||||
|
|
@ -204,6 +210,10 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
|||
String: filter.CountryCode.Value,
|
||||
Valid: filter.CountryCode.Valid,
|
||||
},
|
||||
Flagged: pgtype.Bool{
|
||||
Bool: filter.Flagged.Valid,
|
||||
Valid: filter.Flagged.Valid,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
|
|
@ -234,6 +244,7 @@ func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.Upc
|
|||
StartTime: event.StartTime.Time.UTC(),
|
||||
Source: event.Source.String,
|
||||
Status: domain.EventStatus(event.Status.String),
|
||||
Flagged: event.Flagged,
|
||||
}, nil
|
||||
}
|
||||
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
|
||||
|
|
@ -269,7 +280,6 @@ func (s *Store) UpdateEventStatus(ctx context.Context, eventID string, status do
|
|||
|
||||
}
|
||||
|
||||
|
||||
func (s *Store) UpdateFlagged(ctx context.Context, eventID string, flagged bool) error {
|
||||
return s.queries.UpdateFlagged(ctx, dbgen.UpdateFlaggedParams{
|
||||
ID: eventID,
|
||||
|
|
|
|||
|
|
@ -10,21 +10,16 @@ import (
|
|||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DBSettingList struct {
|
||||
MaxNumberOfOutcomes domain.ValidInt64
|
||||
BetAmountLimit domain.ValidInt64
|
||||
DailyTicketPerIP domain.ValidInt64
|
||||
TotalWinningLimit domain.ValidInt64
|
||||
}
|
||||
|
||||
func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||
var dbSettingList DBSettingList
|
||||
var int64SettingsMap = map[string]*domain.ValidInt64{
|
||||
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||
"bet_amount_limit": &dbSettingList.BetAmountLimit,
|
||||
"daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
||||
"total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
||||
}
|
||||
var dbSettingList domain.DBSettingList
|
||||
// var int64SettingsMap = map[string]*domain.ValidInt64{
|
||||
// "max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||
// "bet_amount_limit": &dbSettingList.BetAmountLimit,
|
||||
// "daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
||||
// "total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
||||
// }
|
||||
|
||||
var int64SettingsMap = domain.ConvertInt64SettingsMap(&dbSettingList)
|
||||
|
||||
for _, setting := range settings {
|
||||
is_setting_unknown := true
|
||||
|
|
@ -54,12 +49,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return domain.SettingList{
|
||||
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
||||
BetAmountLimit: domain.Currency(dbSettingList.BetAmountLimit.Value),
|
||||
DailyTicketPerIP: dbSettingList.DailyTicketPerIP.Value,
|
||||
TotalWinningLimit: domain.Currency(dbSettingList.TotalWinningLimit.Value),
|
||||
}, nil
|
||||
return domain.ConvertDBSetting(dbSettingList), nil
|
||||
}
|
||||
func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
||||
settings, err := s.queries.GetSettings(ctx)
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@ import (
|
|||
type BetStore interface {
|
||||
CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error)
|
||||
CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBetOutcome) (int64, error)
|
||||
GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error)
|
||||
GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
|
||||
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error)
|
||||
GetBetByBranchID(ctx context.Context, BranchID int64) ([]domain.GetBet, error)
|
||||
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
|
||||
GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, error)
|
||||
GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
|
|
@ -41,6 +42,7 @@ var (
|
|||
|
||||
ErrInvalidAmount = errors.New("Invalid amount")
|
||||
ErrBetAmountTooHigh = errors.New("Cannot create a bet with an amount above limit")
|
||||
ErrBetWinningTooHigh = errors.New("Total Winnings over set limit")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
|
@ -49,6 +51,7 @@ type Service struct {
|
|||
prematchSvc odds.ServiceImpl
|
||||
walletSvc wallet.Service
|
||||
branchSvc branch.Service
|
||||
companySvc company.Service
|
||||
settingSvc settings.Service
|
||||
notificationSvc *notificationservice.Service
|
||||
logger *slog.Logger
|
||||
|
|
@ -61,6 +64,7 @@ func NewService(
|
|||
prematchSvc odds.ServiceImpl,
|
||||
walletSvc wallet.Service,
|
||||
branchSvc branch.Service,
|
||||
companySvc company.Service,
|
||||
settingSvc settings.Service,
|
||||
notificationSvc *notificationservice.Service,
|
||||
logger *slog.Logger,
|
||||
|
|
@ -72,6 +76,7 @@ func NewService(
|
|||
prematchSvc: prematchSvc,
|
||||
walletSvc: walletSvc,
|
||||
branchSvc: branchSvc,
|
||||
companySvc: companySvc,
|
||||
settingSvc: settingSvc,
|
||||
notificationSvc: notificationSvc,
|
||||
logger: logger,
|
||||
|
|
@ -206,7 +211,7 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
|
|||
return newOutcome, nil
|
||||
}
|
||||
|
||||
func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID int64, role domain.Role) (domain.CreateBetRes, error) {
|
||||
func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID int64, role domain.Role, companyID domain.ValidInt64) (domain.CreateBetRes, error) {
|
||||
settingsList, err := s.settingSvc.GetSettingList(ctx)
|
||||
|
||||
if req.Amount < 1 {
|
||||
|
|
@ -214,11 +219,11 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
}
|
||||
|
||||
if req.Amount > settingsList.BetAmountLimit.Float32() {
|
||||
return domain.CreateBetRes{}, ErrInvalidAmount
|
||||
return domain.CreateBetRes{}, ErrBetAmountTooHigh
|
||||
}
|
||||
|
||||
if len(req.Outcomes) > int(settingsList.MaxNumberOfOutcomes) {
|
||||
s.mongoLogger.Error("too many outcomes",
|
||||
s.mongoLogger.Info("too many outcomes",
|
||||
zap.Int("count", len(req.Outcomes)),
|
||||
zap.Int64("user_id", userID),
|
||||
)
|
||||
|
|
@ -244,6 +249,16 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
outcomes = append(outcomes, newOutcome)
|
||||
}
|
||||
|
||||
totalWinnings := req.Amount * totalOdds
|
||||
|
||||
if totalWinnings > settingsList.TotalWinningLimit.Float32() {
|
||||
s.mongoLogger.Info("Total Winnings over limit",
|
||||
zap.Float32("Total Odds", totalOdds),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Float32("limit", settingsList.TotalWinningLimit.Float32()))
|
||||
return domain.CreateBetRes{}, ErrBetWinningTooHigh
|
||||
}
|
||||
|
||||
outcomesHash, err := generateOutcomeHash(outcomes)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to generate outcome hash",
|
||||
|
|
@ -254,14 +269,6 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
}
|
||||
|
||||
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||
if err != nil {
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
if count >= 2 {
|
||||
return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice")
|
||||
}
|
||||
|
||||
cashoutID, err := s.GenerateCashoutID()
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to generate cashout ID",
|
||||
zap.Int64("user_id", userID),
|
||||
|
|
@ -269,6 +276,9 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
if count >= 2 {
|
||||
return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice")
|
||||
}
|
||||
|
||||
fastCode := helpers.GenerateFastCode()
|
||||
|
||||
|
|
@ -276,15 +286,14 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: totalOdds,
|
||||
Status: domain.OUTCOME_STATUS_PENDING,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
CashoutID: cashoutID,
|
||||
OutcomesHash: outcomesHash,
|
||||
FastCode: fastCode,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
switch role {
|
||||
case domain.RoleCashier:
|
||||
newBet.IsShopBet = true
|
||||
branch, err := s.branchSvc.GetBranchByCashier(ctx, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get branch by cashier",
|
||||
|
|
@ -294,30 +303,20 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
deductedAmount := req.Amount / 10
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx,
|
||||
branch.WalletID, domain.ToCurrency(deductedAmount), domain.BranchWalletType, domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", deductedAmount))
|
||||
err = s.DeductBetFromBranchWallet(ctx, req.Amount, branch.WalletID, branch.CompanyID, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to deduct from wallet",
|
||||
zap.Int64("wallet_id", branch.WalletID),
|
||||
zap.Float32("amount", deductedAmount),
|
||||
s.mongoLogger.Error("wallet deduction for bet failed",
|
||||
zap.String("role", string(role)),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
newBet.BranchID = domain.ValidInt64{Value: branch.ID, Valid: true}
|
||||
newBet.CompanyID = domain.ValidInt64{Value: branch.CompanyID, Valid: true}
|
||||
newBet.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
||||
newBet.IsShopBet = true
|
||||
|
||||
case domain.RoleBranchManager, domain.RoleAdmin, domain.RoleSuperAdmin:
|
||||
newBet.IsShopBet = true
|
||||
// Branch Manager, Admin and Super Admin are required to pass a branch id if they want to create a bet
|
||||
if req.BranchID == nil {
|
||||
s.mongoLogger.Error("branch ID required for admin/manager",
|
||||
s.mongoLogger.Warn("branch ID required for admin/manager",
|
||||
zap.Int64("user_id", userID),
|
||||
)
|
||||
return domain.CreateBetRes{}, ErrBranchIDRequired
|
||||
|
|
@ -332,87 +331,42 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
deductedAmount := req.Amount / 10
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, branch.WalletID, domain.ToCurrency(deductedAmount), domain.BranchWalletType, domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
}, domain.TRANSFER_DIRECT, fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", deductedAmount))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed",
|
||||
zap.Int64("wallet_id", branch.WalletID),
|
||||
zap.Float32("amount", deductedAmount),
|
||||
if branch.BranchManagerID != userID {
|
||||
s.mongoLogger.Warn("unauthorized branch for branch manager",
|
||||
zap.Int64("branch_id", *req.BranchID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
newBet.BranchID = domain.ValidInt64{Value: branch.ID, Valid: true}
|
||||
newBet.CompanyID = domain.ValidInt64{Value: branch.CompanyID, Valid: true}
|
||||
newBet.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
||||
newBet.IsShopBet = true
|
||||
if companyID.Valid && branch.CompanyID == companyID.Value {
|
||||
s.mongoLogger.Warn("unauthorized company",
|
||||
zap.Int64("branch_id", *req.BranchID),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
err = s.DeductBetFromBranchWallet(ctx, req.Amount, branch.WalletID, branch.CompanyID, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction for bet failed",
|
||||
zap.String("role", string(role)),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
case domain.RoleCustomer:
|
||||
wallets, err := s.walletSvc.GetCustomerWallet(ctx, userID)
|
||||
// Only the customer is able to create a online bet
|
||||
newBet.IsShopBet = false
|
||||
err = s.DeductBetFromCustomerWallet(ctx, req.Amount, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get customer wallets",
|
||||
s.mongoLogger.Error("customer wallet deduction failed",
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
if req.Amount < wallets.RegularBalance.Float32() {
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
domain.ToCurrency(req.Amount), domain.CustomerWalletType, domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT, fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", req.Amount))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
} else {
|
||||
combinedBalance := wallets.RegularBalance + wallets.StaticBalance
|
||||
if req.Amount > combinedBalance.Float32() {
|
||||
return domain.CreateBetRes{}, ErrTotalBalanceNotEnough
|
||||
}
|
||||
// Empty the regular balance
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
wallets.RegularBalance, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", wallets.RegularBalance.Float32()))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
// Empty remaining from static balance
|
||||
remainingAmount := wallets.RegularBalance - domain.Currency(req.Amount)
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.StaticID,
|
||||
remainingAmount, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", remainingAmount.Float32()))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer static wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("static wallet_id", wallets.StaticID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
newBet.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
||||
newBet.IsShopBet = false
|
||||
default:
|
||||
s.mongoLogger.Error("unknown role type",
|
||||
zap.String("role", string(role)),
|
||||
|
|
@ -447,6 +401,100 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Service) DeductBetFromBranchWallet(ctx context.Context, amount float32, walletID int64, companyID int64, userID int64) error {
|
||||
|
||||
company, err := s.companySvc.GetCompanyByID(ctx, companyID)
|
||||
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get company",
|
||||
zap.Int64("company_id", companyID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
deductedAmount := amount * company.DeductedPercentage
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx,
|
||||
walletID, domain.ToCurrency(deductedAmount), domain.BranchWalletType, domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", deductedAmount))
|
||||
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to deduct from wallet",
|
||||
zap.Int64("wallet_id", walletID),
|
||||
zap.Float32("amount", deductedAmount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) DeductBetFromCustomerWallet(ctx context.Context, amount float32, userID int64) error {
|
||||
wallets, err := s.walletSvc.GetCustomerWallet(ctx, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get customer wallets",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
if amount < wallets.RegularBalance.Float32() {
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
domain.ToCurrency(amount), domain.CustomerWalletType, domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT, fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", amount))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
combinedBalance := wallets.RegularBalance + wallets.StaticBalance
|
||||
if amount > combinedBalance.Float32() {
|
||||
return ErrTotalBalanceNotEnough
|
||||
}
|
||||
// Empty the regular balance
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
wallets.RegularBalance, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", wallets.RegularBalance.Float32()))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
// Empty remaining from static balance
|
||||
remainingAmount := wallets.RegularBalance - domain.Currency(amount)
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.StaticID,
|
||||
remainingAmount, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||
fmt.Sprintf("Deducted %v amount from wallet by system while placing bet", remainingAmount.Float32()))
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer static wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("static wallet_id", wallets.StaticID),
|
||||
zap.Float32("amount", amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GenerateRandomBetOutcomes(ctx context.Context, eventID string, sportID int32, HomeTeam, AwayTeam string, StartTime time.Time, numMarkets int) ([]domain.CreateBetOutcome, float32, error) {
|
||||
|
||||
var newOdds []domain.CreateBetOutcome
|
||||
|
|
@ -657,26 +705,38 @@ func (s *Service) PlaceRandomBet(ctx context.Context, userID, branchID int64, le
|
|||
|
||||
// s.logger.Info("Generated Random bet Outcome", "randomOdds", len(randomOdds))
|
||||
|
||||
var cashoutID string
|
||||
|
||||
cashoutID, err = s.GenerateCashoutID()
|
||||
outcomesHash, err := generateOutcomeHash(randomOdds)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("Failed to generate cash out ID",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("branchID", branchID))
|
||||
s.mongoLogger.Error("failed to generate outcome hash",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
randomNumber := strconv.FormatInt(int64(random.Intn(100000000000)), 10)
|
||||
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get bet count",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.String("outcome_hash", outcomesHash),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
if count >= 2 {
|
||||
return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice")
|
||||
}
|
||||
|
||||
fastCode := helpers.GenerateFastCode()
|
||||
|
||||
newBet := domain.CreateBet{
|
||||
Amount: domain.ToCurrency(123.5),
|
||||
TotalOdds: totalOdds,
|
||||
Status: domain.OUTCOME_STATUS_PENDING,
|
||||
FullName: "test" + randomNumber,
|
||||
PhoneNumber: "0900000000",
|
||||
CashoutID: cashoutID,
|
||||
BranchID: domain.ValidInt64{Valid: true, Value: branchID},
|
||||
UserID: domain.ValidInt64{Valid: true, Value: userID},
|
||||
UserID: userID,
|
||||
IsShopBet: true,
|
||||
FastCode: fastCode,
|
||||
}
|
||||
|
||||
bet, err := s.CreateBet(ctx, newBet)
|
||||
|
|
@ -721,17 +781,10 @@ func (s *Service) CreateBetOutcome(ctx context.Context, outcomes []domain.Create
|
|||
func (s *Service) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error) {
|
||||
return s.betStore.GetBetByID(ctx, id)
|
||||
}
|
||||
func (s *Service) GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error) {
|
||||
return s.betStore.GetBetByCashoutID(ctx, id)
|
||||
}
|
||||
func (s *Service) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
|
||||
return s.betStore.GetAllBets(ctx, filter)
|
||||
}
|
||||
|
||||
func (s *Service) GetBetByBranchID(ctx context.Context, branchID int64) ([]domain.GetBet, error) {
|
||||
return s.betStore.GetBetByBranchID(ctx, branchID)
|
||||
}
|
||||
|
||||
func (s *Service) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) {
|
||||
return s.betStore.GetBetByUserID(ctx, UserID)
|
||||
}
|
||||
|
|
@ -948,3 +1001,27 @@ func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
|||
sum := sha256.Sum256([]byte(sb.String()))
|
||||
return hex.EncodeToString(sum[:]), nil
|
||||
}
|
||||
|
||||
func (s *Service) CheckIfBetError(err error) bool {
|
||||
betErrors := []error{
|
||||
ErrNoEventsAvailable,
|
||||
ErrGenerateRandomOutcome,
|
||||
ErrOutcomesNotCompleted,
|
||||
ErrEventHasBeenRemoved,
|
||||
ErrEventHasNotEnded,
|
||||
ErrRawOddInvalid,
|
||||
ErrBranchIDRequired,
|
||||
ErrOutcomeLimit,
|
||||
ErrTotalBalanceNotEnough,
|
||||
ErrInvalidAmount,
|
||||
ErrBetAmountTooHigh,
|
||||
ErrBetWinningTooHigh,
|
||||
}
|
||||
|
||||
for _, e := range betErrors {
|
||||
if errors.Is(err, e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -649,7 +649,7 @@ func (s *Service) fetchReportData(ctx context.Context, period string) (domain.Re
|
|||
totalCashBacks = 0
|
||||
}
|
||||
companyReports = append(companyReports, domain.CompanyReport{
|
||||
CompanyID: row.CompanyID.Int64,
|
||||
CompanyID: row.CompanyID,
|
||||
CompanyName: row.CompanyName,
|
||||
TotalBets: row.TotalBets,
|
||||
TotalCashIn: totalCashIn,
|
||||
|
|
@ -702,7 +702,7 @@ func (s *Service) fetchReportData(ctx context.Context, period string) (domain.Re
|
|||
totalCashBacks = 0
|
||||
}
|
||||
branchReports = append(branchReports, domain.BranchReport{
|
||||
BranchID: row.BranchID.Int64,
|
||||
BranchID: row.BranchID,
|
||||
BranchName: row.BranchName,
|
||||
CompanyID: row.CompanyID,
|
||||
TotalBets: row.TotalBets,
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
|
|||
|
||||
}
|
||||
|
||||
|
||||
if req.Amount < 1 {
|
||||
return domain.Ticket{}, 0, ErrInvalidAmount
|
||||
}
|
||||
|
|
@ -211,7 +210,7 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
|
|||
|
||||
// Check to see if the total winning amount is over a set limit
|
||||
if totalWinnings > settingsList.TotalWinningLimit.Float32() {
|
||||
s.mongoLogger.Error("Total Winnings over limit",
|
||||
s.mongoLogger.Info("Total Winnings over limit",
|
||||
zap.Float32("Total Odds", totalOdds),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Float32("limit", settingsList.TotalWinningLimit.Float32()))
|
||||
|
|
@ -280,3 +279,24 @@ func (s *Service) DeleteTicket(ctx context.Context, id int64) error {
|
|||
func (s *Service) DeleteOldTickets(ctx context.Context) error {
|
||||
return s.ticketStore.DeleteOldTickets(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) CheckTicketError(err error) bool {
|
||||
ticketError := []error{
|
||||
ErrTicketHasExpired,
|
||||
ErrNoEventsAvailable,
|
||||
ErrEventHasBeenRemoved,
|
||||
ErrTooManyOutcomesForTicket,
|
||||
ErrTicketAmountTooHigh,
|
||||
ErrTicketLimitForSingleUser,
|
||||
ErrTicketWinningTooHigh,
|
||||
ErrInvalidAmount,
|
||||
ErrRawOddInvalid,
|
||||
}
|
||||
|
||||
for _, e := range ticketError {
|
||||
if errors.Is(err, e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,7 @@ func (s *Service) CreateShopBet(ctx context.Context, userID int64, role domain.R
|
|||
newBet, err := s.betSvc.PlaceBet(ctx, domain.CreateBetReq{
|
||||
Outcomes: req.Outcomes,
|
||||
Amount: req.Amount,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BranchID: branchID,
|
||||
}, userID, role)
|
||||
}, userID, role, userCompanyID)
|
||||
|
||||
if err != nil {
|
||||
return domain.ShopBet{}, err
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
|
@ -31,28 +32,32 @@ type CreateAdminReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin [post]
|
||||
// @Router /api/v1/admin [post]
|
||||
func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
||||
var companyID domain.ValidInt64
|
||||
var req CreateAdminReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to parse CreateAdmin request",
|
||||
h.mongoLoggerSvc.Info("failed to parse CreateAdmin request",
|
||||
zap.Int64("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
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.mongoLoggerSvc.Error("validation failed for CreateAdmin request",
|
||||
zap.Int64("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
if req.CompanyID == nil {
|
||||
|
|
@ -69,7 +74,7 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Company ID is invalid", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Company ID is invalid:"+err.Error())
|
||||
}
|
||||
companyID = domain.ValidInt64{
|
||||
Value: *req.CompanyID,
|
||||
|
|
@ -95,13 +100,16 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create admin", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create admin:"+err.Error())
|
||||
}
|
||||
|
||||
if req.CompanyID != nil {
|
||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
ID: *req.CompanyID,
|
||||
AdminID: &newUser.ID,
|
||||
AdminID: domain.ValidInt64{
|
||||
Value: newUser.ID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to update company with new admin",
|
||||
|
|
@ -111,7 +119,7 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +160,7 @@ type AdminRes struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin [get]
|
||||
// @Router /api/v1/admin [get]
|
||||
func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
|
|
@ -166,8 +174,8 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.logger.Info("invalid start_time format", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -180,8 +188,8 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.logger.Info("invalid start_time format", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -209,12 +217,16 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
h.mongoLoggerSvc.Error("invalid filter values in GetAllAdmins request",
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("invalid filter values in GetAllAdmins request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
admins, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
|
|
@ -225,7 +237,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Admins", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get Admins"+err.Error())
|
||||
}
|
||||
|
||||
result := make([]AdminRes, len(admins))
|
||||
|
|
@ -241,7 +253,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +295,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/{id} [get]
|
||||
// @Router /api/v1/admin/{id} [get]
|
||||
func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
|
|
@ -294,7 +306,7 @@ func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid admin ID", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid admin ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
|
|
@ -305,7 +317,7 @@ func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get admin", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get admin"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
|
|
@ -316,7 +328,7 @@ func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -365,7 +377,7 @@ type updateAdminReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin/{id} [put]
|
||||
// @Router /api/v1/admin/{id} [put]
|
||||
func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
||||
var req updateAdminReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -374,29 +386,33 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - validation errors",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
AdminIDStr := c.Params("id")
|
||||
AdminID, err := strconv.ParseInt(AdminIDStr, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - invalid Admin ID param",
|
||||
h.mongoLoggerSvc.Info("UpdateAdmin failed - invalid Admin ID param",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("admin_id_param", AdminIDStr),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Admin ID", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Admin ID")
|
||||
}
|
||||
|
||||
var companyID domain.ValidInt64
|
||||
|
|
@ -430,13 +446,16 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update admin", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update admin:"+err.Error())
|
||||
}
|
||||
|
||||
if req.CompanyID != nil {
|
||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
ID: *req.CompanyID,
|
||||
AdminID: &AdminID,
|
||||
AdminID: domain.ValidInt64{
|
||||
Value: AdminID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed to update company",
|
||||
|
|
@ -445,7 +464,7 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", nil, nil)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update company:"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package handlers
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
|
|
@ -36,41 +37,47 @@ type loginCustomerRes struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/login [post]
|
||||
// @Router /api/v1/auth/login [post]
|
||||
func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
||||
var req loginCustomerReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse LoginCustomer request",
|
||||
h.mongoLoggerSvc.Info("Failed to parse LoginCustomer request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
if _, ok := h.validator.Validate(c, req); !ok {
|
||||
h.mongoLoggerSvc.Error("LoginCustomer validation failed",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("request", req),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Request")
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
successRes, err := h.authSvc.Login(c.Context(), req.Email, req.PhoneNumber, req.Password)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Login attempt failed",
|
||||
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrInvalidPassword), errors.Is(err, authentication.ErrUserNotFound):
|
||||
h.mongoLoggerSvc.Info("Login attempt failed: Invalid credentials",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("email", req.Email),
|
||||
zap.String("phone", req.PhoneNumber),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrInvalidPassword), errors.Is(err, authentication.ErrUserNotFound):
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
|
||||
case errors.Is(err, authentication.ErrUserSuspended):
|
||||
h.mongoLoggerSvc.Info("Login attempt failed: User login has been locked",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("email", req.Email),
|
||||
zap.String("phone", req.PhoneNumber),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "User login has been locked")
|
||||
default:
|
||||
h.mongoLoggerSvc.Error("Login failed",
|
||||
|
|
@ -125,7 +132,7 @@ type refreshToken struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/refresh [post]
|
||||
// @Router /api/v1/auth/refresh [post]
|
||||
func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||
|
||||
type loginCustomerRes struct {
|
||||
|
|
@ -136,35 +143,47 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
|
||||
var req refreshToken
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse RefreshToken request",
|
||||
h.mongoLoggerSvc.Info("Failed to parse RefreshToken request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
h.mongoLoggerSvc.Error("RefreshToken validation failed",
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Failed to validate request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
refreshToken, err := h.authSvc.RefreshToken(c.Context(), req.RefreshToken)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Refresh token attempt failed",
|
||||
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrExpiredToken):
|
||||
h.mongoLoggerSvc.Info("Refresh token attempt failed: The refresh token has expired",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("refresh_token", req.RefreshToken),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrExpiredToken):
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
||||
case errors.Is(err, authentication.ErrRefreshTokenNotFound):
|
||||
h.mongoLoggerSvc.Info("Refresh token attempt failed: Refresh token not found",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("refresh_token", req.RefreshToken),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Refresh token not found")
|
||||
default:
|
||||
h.mongoLoggerSvc.Error("Refresh token failed",
|
||||
|
|
@ -184,7 +203,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user information")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user information:"+err.Error())
|
||||
}
|
||||
|
||||
accessToken, err := jwtutil.CreateJwt(user.ID, user.Role, user.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
|
||||
|
|
@ -195,7 +214,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate access token")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate access token:"+err.Error())
|
||||
}
|
||||
|
||||
res := loginCustomerRes{
|
||||
|
|
@ -204,7 +223,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
Role: string(user.Role),
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Refresh token successful",
|
||||
h.mongoLoggerSvc.Info("Token Refreshed Successfully",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int64("user_id", user.ID),
|
||||
zap.String("role", string(user.Role)),
|
||||
|
|
@ -229,39 +248,53 @@ type logoutReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/logout [post]
|
||||
// @Router /api/v1/auth/logout [post]
|
||||
func (h *Handler) LogOutCustomer(c *fiber.Ctx) error {
|
||||
var req logoutReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse LogOutCustomer request",
|
||||
h.mongoLoggerSvc.Info("Failed to parse LogOutCustomer request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
h.mongoLoggerSvc.Error("LogOutCustomer validation failed",
|
||||
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("LogOutCustomer validation failed",
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err := h.authSvc.Logout(c.Context(), req.RefreshToken)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Logout attempt failed",
|
||||
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrExpiredToken):
|
||||
h.mongoLoggerSvc.Info("Logout attempt failed:The refresh token has expired",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("refresh_token", req.RefreshToken),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
switch {
|
||||
case errors.Is(err, authentication.ErrExpiredToken):
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
||||
case errors.Is(err, authentication.ErrRefreshTokenNotFound):
|
||||
h.mongoLoggerSvc.Info("Logout attempt failed: Refresh token not found",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("refresh_token", req.RefreshToken),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Refresh token not found")
|
||||
default:
|
||||
h.mongoLoggerSvc.Error("Logout failed",
|
||||
|
|
@ -269,7 +302,7 @@ func (h *Handler) LogOutCustomer(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Internal server error")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Internal server error"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ import (
|
|||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet [post]
|
||||
// @Router /api/v1/sport/bet [post]
|
||||
func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
var req domain.CreateBetReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -35,16 +36,18 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
res, err := h.CreateBetInternal(c, req, userID, role)
|
||||
res, err := h.CreateBetInternal(c, req, userID, role, companyID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to create bet",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create bet:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet created successfully",
|
||||
|
|
@ -66,10 +69,11 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet/fastcode [post]
|
||||
// @Router /api/v1/sport/bet/fastcode [post]
|
||||
func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
var req struct {
|
||||
FastCode string `json:"fast_code"`
|
||||
|
|
@ -81,27 +85,29 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
bet, err := h.betSvc.GetBetByFastCode(c.Context(), req.FastCode)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("falied to get bet with fast code",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
h.mongoLoggerSvc.Info("failed to get bet with fast code",
|
||||
zap.String("fast_code", req.FastCode),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "falied to get bet with fast code")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to get bet with fast code:"+err.Error())
|
||||
}
|
||||
|
||||
outcomes, err := h.betSvc.GetBetOutcomeByBetID(c.Context(), bet.ID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("falied to get BetOutcomes by BetID",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
h.mongoLoggerSvc.Info("failed to get BetOutcomes by BetID",
|
||||
zap.Int64("bet_id", bet.ID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "falied to get BetOutcomes by BetID")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to get BetOutcomes by BetID:"+err.Error())
|
||||
}
|
||||
|
||||
bet_outcomes := []domain.CreateBetOutcomeReq{}
|
||||
|
|
@ -113,58 +119,43 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
|||
})
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("falied to get user information",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "falied to get user information")
|
||||
}
|
||||
|
||||
// branch, err := h.branchSvc.GetBranchByID(c.Context(), user)
|
||||
// if err != nil {
|
||||
// h.mongoLoggerSvc.Error("falied to get branch of user",
|
||||
// zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "falied to get branch of user")
|
||||
// }
|
||||
|
||||
newReq := domain.CreateBetReq{
|
||||
Amount: float32(bet.Amount),
|
||||
Outcomes: bet_outcomes,
|
||||
BranchID: nil,
|
||||
FullName: user.FirstName,
|
||||
PhoneNumber: user.PhoneNumber,
|
||||
}
|
||||
|
||||
res, err := h.CreateBetInternal(c, newReq, userID, role)
|
||||
res, err := h.CreateBetInternal(c, newReq, userID, role, companyID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to create bet",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Any("newReq", newReq),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to create bet")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create bet:"+err.Error())
|
||||
}
|
||||
|
||||
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), bet.UserID.Value)
|
||||
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), bet.UserID)
|
||||
|
||||
// amount added for fast code owner can be fetched from settings in db
|
||||
amount := domain.Currency(100)
|
||||
settingList, err := h.settingSvc.GetSettingList(c.Context())
|
||||
amount := settingList.AmountForBetReferral
|
||||
|
||||
_, err = h.walletSvc.AddToWallet(c.Context(), wallet.StaticID, amount, domain.ValidInt64{},
|
||||
domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Added %v to static wallet by referring using fast_code", amount.Float32()))
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to add reward to static bet",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Float32("amount", amount.Float32()),
|
||||
zap.Int64("static wallet_id", wallet.StaticID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to add reward to static bet")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to add reward to static bet:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet created successfully",
|
||||
|
|
@ -175,7 +166,7 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", res, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userID int64, role domain.Role) (domain.CreateBetRes, error) {
|
||||
func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userID int64, role domain.Role, companyID domain.ValidInt64) (domain.CreateBetRes, error) {
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
h.mongoLoggerSvc.Error("CreateBet validation failed",
|
||||
|
|
@ -186,19 +177,30 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
|||
return domain.CreateBetRes{}, fmt.Errorf("%s", valErrs)
|
||||
}
|
||||
|
||||
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role)
|
||||
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role, companyID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("PlaceBet failed",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
switch err {
|
||||
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, wallet.ErrBalanceInsufficient:
|
||||
h.mongoLoggerSvc.Info("PlaceBet failed",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("companyID", companyID.Value),
|
||||
zap.String("role", string(role)),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
switch err {
|
||||
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, wallet.ErrBalanceInsufficient:
|
||||
return domain.CreateBetRes{}, fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Error("PlaceBet failed",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("companyID", companyID.Value),
|
||||
zap.String("role", string(role)),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return domain.CreateBetRes{}, fiber.NewError(fiber.StatusInternalServerError, "Unable to create bet")
|
||||
}
|
||||
|
||||
|
|
@ -215,28 +217,28 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
|||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/random/bet [post]
|
||||
// @Router /api/v1/sport/random/bet [post]
|
||||
func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
||||
leagueIDQuery, err := strconv.Atoi(c.Query("league_id"))
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid league id",
|
||||
h.mongoLoggerSvc.Info("invalid league id",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
||||
sportIDQuery, err := strconv.Atoi(c.Query("sport_id"))
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid sport id",
|
||||
h.mongoLoggerSvc.Info("invalid sport id",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid sport id")
|
||||
}
|
||||
|
||||
firstStartTimeQuery := c.Query("first_start_time")
|
||||
|
|
@ -255,12 +257,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
if firstStartTimeQuery != "" {
|
||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid start_time format",
|
||||
h.mongoLoggerSvc.Info("invalid first_start_time format",
|
||||
zap.String("first_start_time", firstStartTimeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid first_start_time format")
|
||||
}
|
||||
firstStartTime = domain.ValidTime{
|
||||
Value: firstStartTimeParsed,
|
||||
|
|
@ -272,12 +275,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
if lastStartTimeQuery != "" {
|
||||
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid start_time format",
|
||||
h.mongoLoggerSvc.Info("invalid last_start_time format",
|
||||
zap.String("last_start_time", lastStartTimeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid last_start_time format")
|
||||
}
|
||||
lastStartTime = domain.ValidTime{
|
||||
Value: lastStartTimeParsed,
|
||||
|
|
@ -287,38 +291,45 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.RandomBetReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse RandomBet request",
|
||||
h.mongoLoggerSvc.Info("Failed to parse RandomBet request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Error("RandomBet validation failed",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
var res domain.CreateBetRes
|
||||
for i := 0; i < int(req.NumberOfBets); i++ {
|
||||
res, err = h.betSvc.PlaceRandomBet(c.Context(), userID, req.BranchID, leagueID, sportID, firstStartTime, lastStartTime)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Random Bet failed",
|
||||
switch err {
|
||||
case bet.ErrNoEventsAvailable:
|
||||
return fiber.NewError(fiber.StatusNotFound, "No events found")
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Error("Random Bet failed place random bet",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("branch_id", req.BranchID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
switch err {
|
||||
case bet.ErrNoEventsAvailable:
|
||||
return fiber.NewError(fiber.StatusBadRequest, "No events found")
|
||||
}
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet:"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,23 +351,24 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet [get]
|
||||
// @Router /api/v1/sport/bet [get]
|
||||
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
branchID := c.Locals("branch_id").(domain.ValidInt64)
|
||||
// companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
// branchID := c.Locals("branch_id").(domain.ValidInt64)
|
||||
|
||||
var isShopBet domain.ValidBool
|
||||
isShopBetQuery := c.Query("is_shop")
|
||||
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
||||
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse is_shop_bet",
|
||||
h.mongoLoggerSvc.Info("failed to parse is_shop_bet",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("is_shop", isShopBetQuery),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_shop_bet")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to parse is_shop_bet")
|
||||
}
|
||||
isShopBet = domain.ValidBool{
|
||||
Value: isShopBetParse,
|
||||
|
|
@ -375,8 +387,13 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("time", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -389,8 +406,13 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("created_after", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -398,24 +420,19 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Filters - BranchID: %+v, CompanyID: %+v, IsShopBet: %+v, Query: %+v, CreatedBefore: %+v, CreatedAfter: %+v\n",
|
||||
branchID, companyID, isShopBet, searchString, createdBefore, createdAfter)
|
||||
|
||||
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
|
||||
BranchID: branchID,
|
||||
CompanyID: companyID,
|
||||
IsShopBet: isShopBet,
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get bets",
|
||||
h.mongoLoggerSvc.Error("Failed to get all bets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets፡"+err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.BetRes, len(bets))
|
||||
|
|
@ -423,11 +440,6 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
res[i] = domain.ConvertBet(bet)
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("All bets retrieved successfully",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All bets retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
|
|
@ -441,12 +453,12 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet/{id} [get]
|
||||
// @Router /api/v1/sport/bet/{id} [get]
|
||||
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||
betID := c.Params("id")
|
||||
id, err := strconv.ParseInt(betID, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid bet ID",
|
||||
h.mongoLoggerSvc.Info("Invalid bet ID",
|
||||
zap.String("betID", betID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
|
|
@ -457,7 +469,7 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
|||
|
||||
bet, err := h.betSvc.GetBetByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get bet by ID",
|
||||
h.mongoLoggerSvc.Info("Failed to get bet by ID",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusNotFound),
|
||||
zap.Error(err),
|
||||
|
|
@ -468,47 +480,11 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
|||
|
||||
res := domain.ConvertBet(bet)
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetBetByCashoutID godoc
|
||||
// @Summary Gets bet by cashout id
|
||||
// @Description Gets a single bet by cashout id
|
||||
// @Tags bet
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "cashout ID"
|
||||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet/cashout/{id} [get]
|
||||
func (h *Handler) GetBetByCashoutID(c *fiber.Ctx) error {
|
||||
cashoutID := c.Params("id")
|
||||
|
||||
bet, err := h.betSvc.GetBetByCashoutID(c.Context(), cashoutID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get bet by cashout ID",
|
||||
zap.String("cashoutID", cashoutID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bet", err, nil)
|
||||
}
|
||||
|
||||
res := domain.ConvertBet(bet)
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet retrieved successfully by cashout ID",
|
||||
zap.String("cashoutID", cashoutID),
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
||||
// zap.Int64("betID", id),
|
||||
// zap.Int("status_code", fiber.StatusOK),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
||||
}
|
||||
|
|
@ -528,7 +504,7 @@ type UpdateCashOutReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet/{id} [patch]
|
||||
// @Router /api/v1/sport/bet/{id} [patch]
|
||||
func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
||||
type UpdateCashOutReq struct {
|
||||
CashedOut bool `json:"cashed_out" validate:"required" example:"true"`
|
||||
|
|
@ -554,11 +530,15 @@ func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request body", err, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to parse request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.betSvc.UpdateCashOut(c.Context(), id, req.CashedOut)
|
||||
|
|
@ -591,7 +571,7 @@ func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet/{id} [delete]
|
||||
// @Router /api/v1/sport/bet/{id} [delete]
|
||||
func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
||||
betID := c.Params("id")
|
||||
id, err := strconv.ParseInt(betID, 10, 64)
|
||||
|
|
@ -613,7 +593,7 @@ func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
|||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete bet")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete bet:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet removed successfully",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (h *Handler) CreateBonusMultiplier(c *fiber.Ctx) error {
|
||||
|
|
@ -12,8 +15,13 @@ func (h *Handler) CreateBonusMultiplier(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("failed to parse bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.logger.Error("failed to parse bonus multiplier request", "error", err)
|
||||
h.mongoLoggerSvc.Info("failed to parse bonus multiplier",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
// currently only one multiplier is allowed
|
||||
|
|
@ -21,29 +29,42 @@ func (h *Handler) CreateBonusMultiplier(c *fiber.Ctx) error {
|
|||
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to get bonus multiplier",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if len(multipliers) > 0 {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "only one multiplier is allowed")
|
||||
}
|
||||
|
||||
if err := h.bonusSvc.CreateBonusMultiplier(c.Context(), req.Multiplier, req.BalanceCap); err != nil {
|
||||
h.logger.Error("failed to create bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "failed to create bonus mulitplier", nil, nil)
|
||||
h.mongoLoggerSvc.Error("failed to create bonus multiplier",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "failed to create bonus multiplier"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Create bonus mulitplier successfully", nil, nil)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Create bonus multiplier successfully", nil, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) GetBonusMultiplier(c *fiber.Ctx) error {
|
||||
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("failed to get bonus multiplier",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Fetched bonus mulitplier successfully", multipliers, nil)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Fetched bonus multiplier successfully", multipliers, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateBonusMultiplier(c *fiber.Ctx) error {
|
||||
|
|
@ -54,14 +75,24 @@ func (h *Handler) UpdateBonusMultiplier(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("failed to parse bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("failed to parse bonus multiplier",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if err := h.bonusSvc.UpdateBonusMultiplier(c.Context(), req.ID, req.Multiplier, req.BalanceCap); err != nil {
|
||||
h.logger.Error("failed to update bonus multiplier", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "failed to update bonus mulitplier", nil, nil)
|
||||
h.mongoLoggerSvc.Error("failed to update bonus multiplier",
|
||||
zap.Int64("id", req.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "failed to update bonus multiplier:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Updated bonus mulitplier successfully", nil, nil)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Updated bonus multiplier successfully", nil, nil)
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CreateCashierReq struct {
|
||||
|
|
@ -32,7 +33,7 @@ type CreateCashierReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashiers [post]
|
||||
// @Router /api/v1/cashiers [post]
|
||||
func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
||||
|
||||
// Get user_id from middleware
|
||||
|
|
@ -40,19 +41,33 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
|||
|
||||
var req CreateCashierReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("failed to parse CreateCashier request body",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate CreateCashier",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
// Cashiers inherit the company id from the branch id
|
||||
// TODO add a check here to make sure that the admin/manager if from same company
|
||||
branch, err := h.branchSvc.GetBranchByID(c.Context(), req.BranchID)
|
||||
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID is invalid", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Branch ID is invalid")
|
||||
}
|
||||
userRequest := domain.CreateUserReq{
|
||||
FirstName: req.FirstName,
|
||||
|
|
@ -70,14 +85,25 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
|||
fmt.Print(req.Suspended)
|
||||
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest, true)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to create cashier user",
|
||||
zap.Any("userRequest", userRequest),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create cashier user:"+err.Error())
|
||||
}
|
||||
|
||||
err = h.branchSvc.CreateBranchCashier(c.Context(), req.BranchID, newUser.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
|
||||
h.mongoLoggerSvc.Error("failed to create branch cashier",
|
||||
zap.Int64("branchID", req.BranchID),
|
||||
zap.Int64("userID", newUser.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create branch cashier:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Cashier created successfully", nil, nil)
|
||||
|
||||
|
|
@ -111,17 +137,22 @@ type GetCashierRes struct {
|
|||
// @Produce json
|
||||
// @Param page query int false "Page number"
|
||||
// @Param page_size query int false "Page size"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Success 200 {array} GetCashierRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashiers [get]
|
||||
// @Router /api/v1/cashiers [get]
|
||||
func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
|
||||
h.mongoLoggerSvc.Error("Cannot get company ID in context",
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID in context")
|
||||
}
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
|
|
@ -134,8 +165,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("createdBefore", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -148,8 +184,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("created_after", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -174,7 +215,16 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate filters for GetAllCashier",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), domain.UserFilter{
|
||||
|
|
@ -183,8 +233,12 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllCashiers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
||||
h.mongoLoggerSvc.Error("failed to get all cashiers",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get cashiers:"+err.Error())
|
||||
}
|
||||
|
||||
var result []GetCashierRes = make([]GetCashierRes, 0, len(cashiers))
|
||||
|
|
@ -195,8 +249,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &cashier.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", cashier.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", cashier.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +295,7 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashier/{id} [get]
|
||||
// @Router /api/v1/cashier/{id} [get]
|
||||
func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
|
||||
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
||||
// filter := user.Filter{
|
||||
|
|
@ -256,22 +315,37 @@ func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
|
|||
stringID := c.Params("id")
|
||||
cashierID, err := strconv.ParseInt(stringID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to fetch user using UserID", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("failed to parse user_id",
|
||||
zap.String("stringID", stringID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid cashier ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetCashierByID(c.Context(), cashierID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Get User By ID failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Get User By ID failed",
|
||||
zap.Int64("cashierID", cashierID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get cashiers:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "cashierID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
|
@ -316,24 +390,42 @@ type updateCashierReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashiers/{id} [put]
|
||||
// @Router /api/v1/cashiers/{id} [put]
|
||||
func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
||||
cashierIdStr := c.Params("id")
|
||||
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("UpdateCashier invalid cashier ID",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid cashier ID")
|
||||
}
|
||||
var req updateCashierReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
||||
h.mongoLoggerSvc.Info("UpdateCashier failed to parse request body",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate update cashier request",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
|
||||
|
|
@ -353,8 +445,14 @@ func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
|||
},
|
||||
)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update cashier", nil, nil)
|
||||
h.mongoLoggerSvc.Error("failed to update cashier",
|
||||
zap.Int64("userID", cashierId),
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update cashier"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Cashier updated successfully", nil, nil)
|
||||
|
||||
|
|
|
|||
1
internal/web_server/handlers/common.go
Normal file
1
internal/web_server/handlers/common.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package handlers
|
||||
|
|
@ -1,92 +1,60 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"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"
|
||||
)
|
||||
|
||||
type CreateCompanyReq struct {
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
}
|
||||
type UpdateCompanyReq struct {
|
||||
Name *string `json:"name,omitempty" example:"CompanyName"`
|
||||
AdminID *int64 `json:"admin_id,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
type CompanyRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
}
|
||||
|
||||
type GetCompanyRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Name string `json:"name" example:"CompanyName"`
|
||||
AdminID int64 `json:"admin_id" example:"1"`
|
||||
WalletID int64 `json:"wallet_id" example:"1"`
|
||||
WalletBalance float32 `json:"balance" example:"1"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
AdminFirstName string `json:"admin_first_name" example:"John"`
|
||||
AdminLastName string `json:"admin_last_name" example:"Doe"`
|
||||
AdminPhoneNumber string `json:"admin_phone_number" example:"1234567890"`
|
||||
}
|
||||
|
||||
func convertCompany(company domain.Company) CompanyRes {
|
||||
return CompanyRes{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
}
|
||||
}
|
||||
|
||||
func convertGetCompany(company domain.GetCompany) GetCompanyRes {
|
||||
return GetCompanyRes{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
AdminID: company.AdminID,
|
||||
WalletID: company.WalletID,
|
||||
WalletBalance: company.WalletBalance.Float32(),
|
||||
IsActive: company.IsWalletActive,
|
||||
AdminFirstName: company.AdminFirstName,
|
||||
AdminLastName: company.AdminLastName,
|
||||
AdminPhoneNumber: company.AdminPhoneNumber,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateCompany godoc
|
||||
// @Summary Create a company
|
||||
// @Description Creates a company
|
||||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param createCompany body CreateCompanyReq true "Creates company"
|
||||
// @Success 200 {object} CompanyRes
|
||||
// @Param createCompany body domain.CreateCompanyReq true "Creates company"
|
||||
// @Success 200 {object} domain.CompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /company [post]
|
||||
// @Router /api/v1/company [post]
|
||||
func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
||||
var req CreateCompanyReq
|
||||
var req domain.CreateCompanyReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CreateCompanyReq failed",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate create company",
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), req.AdminID)
|
||||
if err != nil {
|
||||
h.logger.Error("Error fetching user", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get user", err, nil)
|
||||
h.mongoLoggerSvc.Error("Error fetching user",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
// Create Company Wallet
|
||||
|
|
@ -98,8 +66,13 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Create Company Wallet failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create company wallet", err, nil)
|
||||
h.mongoLoggerSvc.Error("Create Company Wallet failed",
|
||||
zap.Int64("admin", req.AdminID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{
|
||||
|
|
@ -109,20 +82,29 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Internal server error",
|
||||
})
|
||||
h.mongoLoggerSvc.Error("CreateCompanyReq failed to create company",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.String("name", req.Name),
|
||||
zap.String("Name", req.Name),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
err = h.userSvc.UpdateUserCompany(c.Context(), user.ID, company.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Internal server error",
|
||||
})
|
||||
h.mongoLoggerSvc.Error("Failed to update user company",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.Int64("companyID", company.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
res := convertCompany(company)
|
||||
res := domain.ConvertCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
|
||||
}
|
||||
|
|
@ -133,10 +115,10 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
|||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} CompanyRes
|
||||
// @Success 200 {array} domain.GetCompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /company [get]
|
||||
// @Router /api/v1/company [get]
|
||||
func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
|
|
@ -149,8 +131,13 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("createdBeforeQuery", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -163,8 +150,13 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("created_after", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -178,14 +170,18 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
|||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get companies", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get companies",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
var result []GetCompanyRes = make([]GetCompanyRes, 0, len(companies))
|
||||
var result []domain.GetCompanyRes = make([]domain.GetCompanyRes, 0, len(companies))
|
||||
|
||||
for _, company := range companies {
|
||||
result = append(result, convertGetCompany(company))
|
||||
result = append(result, domain.ConvertGetCompany(company))
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
|
||||
|
|
@ -199,27 +195,37 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Company ID"
|
||||
// @Success 200 {object} CompanyRes
|
||||
// @Success 200 {object} domain.GetCompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /company/{id} [get]
|
||||
// @Router /api/v1/company/{id} [get]
|
||||
func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
|
||||
|
||||
companyID := c.Params("id")
|
||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid company ID",
|
||||
zap.String("companyID", companyID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid company ID")
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), id)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get company by ID", "companyID", id, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get company by ID",
|
||||
zap.Int64("companyID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := convertGetCompany(company)
|
||||
res := domain.ConvertGetCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
|
||||
}
|
||||
|
|
@ -230,24 +236,33 @@ func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
|
|||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} CompanyRes
|
||||
// @Success 200 {object} domain.GetCompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin-company [get]
|
||||
// @Router /api/v1/admin-company [get]
|
||||
func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
if !companyID.Valid {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid company ID", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Invalid company ID",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid company ID")
|
||||
}
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get company by ID", "companyID", companyID.Value, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get company by ID",
|
||||
zap.Int64("companyID", companyID.Value),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := convertGetCompany(company)
|
||||
res := domain.ConvertGetCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
|
||||
}
|
||||
|
|
@ -258,25 +273,34 @@ func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error {
|
|||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} CompanyRes
|
||||
// @Success 200 {array} domain.CompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /search/company [get]
|
||||
// @Router /api/v1/search/company [get]
|
||||
func (h *Handler) SearchCompany(c *fiber.Ctx) error {
|
||||
searchQuery := c.Query("q")
|
||||
if searchQuery == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Search query is required",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Search query is required")
|
||||
}
|
||||
companies, err := h.companySvc.SearchCompanyByName(c.Context(), searchQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get companies", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to get companies",
|
||||
zap.String("search query", searchQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
var result []GetCompanyRes = make([]GetCompanyRes, 0, len(companies))
|
||||
var result []domain.GetCompanyRes = make([]domain.GetCompanyRes, 0, len(companies))
|
||||
|
||||
for _, company := range companies {
|
||||
result = append(result, convertGetCompany(company))
|
||||
result = append(result, domain.ConvertGetCompany(company))
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
|
||||
|
|
@ -290,42 +314,63 @@ func (h *Handler) SearchCompany(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Company ID"
|
||||
// @Param updateCompany body UpdateCompanyReq true "Update Company"
|
||||
// @Success 200 {object} CompanyRes
|
||||
// @Param updateCompany body domain.UpdateCompanyReq true "Update Company"
|
||||
// @Success 200 {object} domain.CompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /company/{id} [put]
|
||||
// @Router /api/v1/company/{id} [put]
|
||||
func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
|
||||
|
||||
companyID := c.Params("id")
|
||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid company ID",
|
||||
zap.String("companyID", companyID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid company ID")
|
||||
}
|
||||
|
||||
var req UpdateCompanyReq
|
||||
var req domain.UpdateCompanyReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("UpdateCompanyReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("UpdateCompanyReq failed",
|
||||
zap.String("companyID", companyID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("UpdateCompanyReq failed to validate",
|
||||
zap.String("companyID", companyID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
company, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||
ID: id,
|
||||
Name: req.Name,
|
||||
AdminID: req.AdminID,
|
||||
})
|
||||
company, err := h.companySvc.UpdateCompany(c.Context(), domain.ConvertUpdateCompanyReq(req))
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update company", "companyID", id, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to update company",
|
||||
zap.Int64("companyID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := convertCompany(company)
|
||||
res := domain.ConvertCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil)
|
||||
|
||||
|
|
@ -341,21 +386,31 @@ func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /company/{id} [delete]
|
||||
// @Router /api/v1/company/{id} [delete]
|
||||
func (h *Handler) DeleteCompany(c *fiber.Ctx) error {
|
||||
|
||||
companyID := c.Params("id")
|
||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid Company ID", "companyID", companyID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Company ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid Company ID",
|
||||
zap.String("companyID", companyID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Company ID")
|
||||
}
|
||||
|
||||
err = h.companySvc.DeleteCompany(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to delete by ID", "Company ID", id, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Company", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to delete by ID",
|
||||
zap.Int64("Company ID", id),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
|
@ -8,9 +9,9 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
||||
type CustomersRes struct {
|
||||
ID int64 `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
|
|
@ -26,6 +27,7 @@ type CustomersRes struct {
|
|||
SuspendedAt time.Time `json:"suspended_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
}
|
||||
|
||||
// GetAllCustomers godoc
|
||||
// @Summary Get all Customers
|
||||
// @Description Get all Customers
|
||||
|
|
@ -38,13 +40,18 @@ type CustomersRes struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /customer [get]
|
||||
// @Router /api/v1/customer [get]
|
||||
func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
// Checking to make sure that admin user has a company id in the token
|
||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
||||
h.mongoLoggerSvc.Error("Cannot get company ID from context",
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
|
||||
}
|
||||
|
||||
|
|
@ -59,8 +66,13 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("createdBefore", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -73,8 +85,13 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("createdAfter", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -99,12 +116,27 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
}
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate GetAllCustomer filters",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
customers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllCustomers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Customers", err, nil)
|
||||
h.mongoLoggerSvc.Error("GetAllCustomers failed to get all users",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get Customers:"+err.Error())
|
||||
}
|
||||
|
||||
var result []CustomersRes = make([]CustomersRes, len(customers))
|
||||
|
|
@ -114,8 +146,14 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &customer.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", customer.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", customer.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError,
|
||||
"Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
}
|
||||
result[index] = CustomersRes{
|
||||
|
|
@ -150,7 +188,7 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /customer/{id} [get]
|
||||
// @Router /api/v1/customer/{id} [get]
|
||||
func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
|
|
@ -160,14 +198,25 @@ func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
|
|||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get customers")
|
||||
h.mongoLoggerSvc.Error("Failed to get customers",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get customers:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -210,26 +259,45 @@ type updateCustomerReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /customer/{id} [put]
|
||||
// @Router /api/v1/customer/{id} [put]
|
||||
func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
|
||||
|
||||
var req updateCustomerReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
||||
h.mongoLoggerSvc.Error("UpdateCustomers invalid request body",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate UpdateCustomerReq",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("ErrMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
CustomersIdStr := c.Params("id")
|
||||
CustomersId, err := strconv.ParseInt(CustomersIdStr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Customers ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid Customers ID",
|
||||
zap.String("userID", CustomersIdStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Customers ID")
|
||||
}
|
||||
|
||||
// var companyID domain.ValidInt64
|
||||
|
|
@ -262,8 +330,13 @@ func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
|
|||
},
|
||||
)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Customers", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to update Customers",
|
||||
zap.Int64("userID", CustomersId),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update Customers:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Customers updated successfully", nil, nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"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"
|
||||
)
|
||||
|
||||
// @Summary Retrieve all upcoming events
|
||||
|
|
@ -24,7 +25,7 @@ import (
|
|||
// @Param last_start_time query string false "End Time"
|
||||
// @Success 200 {array} domain.UpcomingEvent
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /events [get]
|
||||
// @Router /api/v1/events [get]
|
||||
func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
|
|
@ -42,8 +43,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
if leagueIDQuery != "" {
|
||||
leagueIDInt, err := strconv.Atoi(leagueIDQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid league id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
|
||||
h.mongoLoggerSvc.Error("invalid league id",
|
||||
zap.String("league_id", leagueIDQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
leagueID = domain.ValidInt32{
|
||||
Value: int32(leagueIDInt),
|
||||
|
|
@ -55,8 +61,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
if sportIDQuery != "" {
|
||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid sport id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid sport id",
|
||||
zap.String("sportID", sportIDQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid sport id")
|
||||
}
|
||||
sportID = domain.ValidInt32{
|
||||
Value: int32(sportIDint),
|
||||
|
|
@ -68,8 +79,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
if firstStartTimeQuery != "" {
|
||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||
zap.String("first_start_time", firstStartTimeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
firstStartTime = domain.ValidTime{
|
||||
Value: firstStartTimeParsed,
|
||||
|
|
@ -82,8 +98,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
if lastStartTimeQuery != "" {
|
||||
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||
zap.String("last_start_time", lastStartTimeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
lastStartTime = domain.ValidTime{
|
||||
Value: lastStartTimeParsed,
|
||||
|
|
@ -97,9 +118,25 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
Valid: countryCodeQuery != "",
|
||||
}
|
||||
|
||||
|
||||
flaggedQuery := c.Query("flagged")
|
||||
if flaggedQuery != "" &&
|
||||
var flagged domain.ValidBool
|
||||
if flaggedQuery != "" {
|
||||
flaggedParsed, err := strconv.ParseBool(flaggedQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse flagged",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_shop_bet")
|
||||
}
|
||||
|
||||
flagged = domain.ValidBool{
|
||||
Value: flaggedParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(
|
||||
c.Context(), domain.EventFilter{
|
||||
SportID: sportID,
|
||||
|
|
@ -109,12 +146,17 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
|||
Limit: limit,
|
||||
Offset: offset,
|
||||
CountryCode: countryCode,
|
||||
Flagged: flagged,
|
||||
})
|
||||
|
||||
// fmt.Printf("League ID: %v", leagueID)
|
||||
if err != nil {
|
||||
h.logger.Error("getting error", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to retrieve all upcoming events",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil, page, int(total))
|
||||
|
|
@ -141,14 +183,18 @@ type TopLeague struct {
|
|||
// @Produce json
|
||||
// @Success 200 {array} TopLeague
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /top-leagues [get]
|
||||
// @Router /api/v1/top-leagues [get]
|
||||
func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
||||
|
||||
leagues, err := h.leagueSvc.GetFeaturedLeagues(c.Context())
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Error while fetching top leagues", "err", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get featured leagues", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Error while fetching top leagues",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
var topLeague []TopLeague = make([]TopLeague, 0, len(leagues))
|
||||
|
|
@ -161,8 +207,12 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
|||
},
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("Error while fetching events for top league %v \n", league.ID)
|
||||
h.logger.Error("Error while fetching events for top league", "League ID", league.ID)
|
||||
h.mongoLoggerSvc.Warn("Error while fetching events for top league",
|
||||
zap.Int64("LeagueID", league.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
}
|
||||
topLeague = append(topLeague, TopLeague{
|
||||
LeagueID: league.ID,
|
||||
|
|
@ -189,17 +239,28 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} domain.UpcomingEvent
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /events/{id} [get]
|
||||
// @Router /api/v1/events/{id} [get]
|
||||
func (h *Handler) GetUpcomingEventByID(c *fiber.Ctx) error {
|
||||
|
||||
id := c.Params("id")
|
||||
if id == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to parse event id",
|
||||
zap.String("id", id),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing id")
|
||||
}
|
||||
|
||||
event, err := h.eventSvc.GetUpcomingEventByID(c.Context(), id)
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get upcoming event by id",
|
||||
zap.String("eventID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
|
||||
|
|
@ -219,13 +280,19 @@ type UpdateEventStatusReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /events/{id} [delete]
|
||||
// @Router /api/v1/events/{id} [delete]
|
||||
func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error {
|
||||
eventID := c.Params("id")
|
||||
err := h.eventSvc.UpdateEventStatus(c.Context(), eventID, domain.STATUS_REMOVED)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update event status", "eventID", eventID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to update event status",
|
||||
zap.String("EventID", eventID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update event status")
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
|
||||
|
|
@ -246,13 +313,19 @@ type UpdateEventFlaggedReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /events/{id}/flag [put]
|
||||
// @Router /api/v1/events/{id}/flag [put]
|
||||
func (h *Handler) UpdateEventFlagged(c *fiber.Ctx) error {
|
||||
eventID := c.Params("id")
|
||||
|
||||
var req UpdateEventFlaggedReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to parse user id",
|
||||
zap.String("eventID", eventID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -262,12 +335,23 @@ func (h *Handler) UpdateEventFlagged(c *fiber.Ctx) error {
|
|||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Error("Failed to update event flagged",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
err := h.eventSvc.UpdateFlagged(c.Context(), eventID, req.Flagged)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update event flagged", "eventID", eventID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to update event flagged",
|
||||
zap.String("eventID", eventID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package handlers
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// CreateIssue godoc
|
||||
|
|
@ -24,12 +26,25 @@ func (h *Handler) CreateIssue(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.ReportedIssueReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Invalid request body",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
created, err := h.issueReportingSvc.CreateReportedIssue(c.Context(), req, userID, role)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
h.mongoLoggerSvc.Error("Failed to report issue",
|
||||
zap.String("role", string(role)),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "failed to report issue:"+err.Error())
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(created)
|
||||
|
|
@ -50,6 +65,12 @@ func (h *Handler) CreateIssue(c *fiber.Ctx) error {
|
|||
func (h *Handler) GetUserIssues(c *fiber.Ctx) error {
|
||||
userID, err := strconv.ParseInt(c.Params("user_id"), 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to parse user id",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +78,13 @@ func (h *Handler) GetUserIssues(c *fiber.Ctx) error {
|
|||
|
||||
issues, err := h.issueReportingSvc.GetIssuesForUser(c.Context(), userID, limit, offset)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
h.mongoLoggerSvc.Error("Failed to get user issue",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get user issue"+err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(issues)
|
||||
|
|
@ -78,7 +105,14 @@ func (h *Handler) GetAllIssues(c *fiber.Ctx) error {
|
|||
|
||||
issues, err := h.issueReportingSvc.GetAllIssues(c.Context(), limit, offset)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
h.mongoLoggerSvc.Error("Failed to get all issues",
|
||||
zap.Int("limit", limit),
|
||||
zap.Int("offset", offset),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get all issues:"+err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(issues)
|
||||
|
|
@ -104,11 +138,24 @@ func (h *Handler) UpdateIssueStatus(c *fiber.Ctx) error {
|
|||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.BodyParser(&body); err != nil || body.Status == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status payload")
|
||||
h.mongoLoggerSvc.Info("Invalid status payload",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid status payload"+err.Error())
|
||||
}
|
||||
|
||||
if err := h.issueReportingSvc.UpdateIssueStatus(c.Context(), issueID, body.Status); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to update issue status",
|
||||
zap.Int64("issueID", issueID),
|
||||
zap.String("status", body.Status),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
|
|
@ -130,6 +177,12 @@ func (h *Handler) DeleteIssue(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.issueReportingSvc.DeleteIssue(c.Context(), issueID); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to delete issue",
|
||||
zap.Int64("issueID", issueID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ package handlers
|
|||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"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"
|
||||
)
|
||||
|
||||
// GetAllLeagues godoc
|
||||
|
|
@ -18,7 +20,7 @@ import (
|
|||
// @Success 200 {array} domain.League
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /leagues [get]
|
||||
// @Router /api/v1/leagues [get]
|
||||
func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
||||
page := c.QueryInt("page", 1)
|
||||
pageSize := c.QueryInt("page_size", 10)
|
||||
|
|
@ -49,8 +51,13 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
if sportIDQuery != "" {
|
||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid sport id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid sport id",
|
||||
zap.String("sport_id", sportIDQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid sport id")
|
||||
}
|
||||
sportID = domain.ValidInt32{
|
||||
Value: int32(sportIDint),
|
||||
|
|
@ -68,8 +75,12 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
|||
|
||||
if err != nil {
|
||||
fmt.Printf("Error fetching league %v \n", err)
|
||||
h.logger.Error("Failed to get leagues", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get leagues", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get all leagues",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get leagues:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All leagues retrieved", leagues, nil)
|
||||
}
|
||||
|
|
@ -78,59 +89,132 @@ type SetLeagueActiveReq struct {
|
|||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
// SetLeagueActive godoc
|
||||
// @Summary Set the league to active
|
||||
// @Description Set the league to active
|
||||
// @Tags leagues
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "League ID"
|
||||
// @Param active body SetLeagueActiveReq true "League Active Request"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/leagues/{id}/set-active [put]
|
||||
func (h *Handler) SetLeagueActive(c *fiber.Ctx) error {
|
||||
fmt.Printf("Set Active Leagues")
|
||||
leagueIdStr := c.Params("id")
|
||||
if leagueIdStr == "" {
|
||||
response.WriteJSON(c, fiber.StatusBadRequest, "Missing league id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing league id")
|
||||
}
|
||||
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||
if err != nil {
|
||||
response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
||||
var req SetLeagueActiveReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("SetLeagueReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to parse request", err, nil)
|
||||
h.mongoLoggerSvc.Error("SetLeagueReq failed to parse request body",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse request:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate SetLeagueActiveReq",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
if err := h.leagueSvc.SetLeagueActive(c.Context(), int64(leagueId), req.IsActive); err != nil {
|
||||
response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update league", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to update league active",
|
||||
zap.Int64("userID", int64(leagueId)),
|
||||
zap.Bool("is_active", req.IsActive),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update league:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) SetLeagueAsFeatured(c *fiber.Ctx) error {
|
||||
fmt.Printf("Set Active Leagues")
|
||||
type SetLeagueAsFeatured struct {
|
||||
IsFeatured bool `json:"is_featured" example:"true"`
|
||||
}
|
||||
|
||||
// SetLeagueFeatured godoc
|
||||
// @Summary Set the league to featured/un-featured
|
||||
// @Description Set the league to featured/un-featured
|
||||
// @Tags leagues
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "League ID"
|
||||
// @Param active body SetLeagueAsFeatured true "League Featured Request"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/leagues/{id}/featured [put]
|
||||
func (h *Handler) SetLeagueFeatured(c *fiber.Ctx) error {
|
||||
leagueIdStr := c.Params("id")
|
||||
if leagueIdStr == "" {
|
||||
response.WriteJSON(c, fiber.StatusBadRequest, "Missing league id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing league id")
|
||||
}
|
||||
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||
if err != nil {
|
||||
response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
|
||||
}
|
||||
|
||||
var req SetLeagueActiveReq
|
||||
var req SetLeagueAsFeatured
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("SetLeagueReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to parse request", err, nil)
|
||||
h.logger.Error("SetLeagueFeaturedReq failed", "error", err)
|
||||
h.mongoLoggerSvc.Info("SetLeagueFeaturedReq failed to parse request body",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse request body:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate SetLeagueFeaturedReq",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
|
||||
if err := h.leagueSvc.SetLeagueActive(c.Context(), int64(leagueId), req.IsActive); err != nil {
|
||||
response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update league", err, nil)
|
||||
}
|
||||
err = h.leagueSvc.UpdateLeague(c.Context(), domain.UpdateLeague{
|
||||
ID: int64(leagueId),
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to update league",
|
||||
zap.Int64("leagueID", int64(leagueId)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update league:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
|
@ -8,6 +9,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CreateManagerReq struct {
|
||||
|
|
@ -30,7 +32,7 @@ type CreateManagerReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /managers [post]
|
||||
// @Router /api/v1/managers [post]
|
||||
func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||
|
||||
// Get user_id from middleware
|
||||
|
|
@ -38,11 +40,26 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
var req CreateManagerReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CreateManager failed to create manager",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate CreateManager",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
var companyID domain.ValidInt64
|
||||
|
|
@ -50,7 +67,11 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
if role == domain.RoleSuperAdmin {
|
||||
if req.CompanyID == nil {
|
||||
h.logger.Error("RegisterUser failed error: company id is required")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", "Company ID is required", nil)
|
||||
h.mongoLoggerSvc.Info("RegisterUser failed error: company id is required",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Company ID is required for super-admin")
|
||||
}
|
||||
companyID = domain.ValidInt64{
|
||||
Value: *req.CompanyID,
|
||||
|
|
@ -71,8 +92,12 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
}
|
||||
_, err := h.userSvc.CreateUser(c.Context(), user, true)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateManager failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create manager", nil, nil)
|
||||
h.mongoLoggerSvc.Error("CreateManager failed to create manager",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create manager:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Manager created successfully", nil, nil)
|
||||
|
||||
|
|
@ -106,14 +131,19 @@ type ManagersRes struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /managers [get]
|
||||
// @Router /api/v1/managers [get]
|
||||
func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
// Checking to make sure that admin user has a company id in the token
|
||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
|
||||
h.mongoLoggerSvc.Error("Cannot get company ID from context",
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID from context")
|
||||
}
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
|
|
@ -127,8 +157,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("created_before", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -141,8 +176,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("created_after", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -167,12 +207,28 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
|||
}
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate get all filters",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
managers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllManagers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", err, nil)
|
||||
h.mongoLoggerSvc.Error("GetAllManagers failed to get all managers",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get Managers"+err.Error())
|
||||
}
|
||||
|
||||
var result []ManagersRes = make([]ManagersRes, len(managers))
|
||||
|
|
@ -182,8 +238,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
|||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &manager.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", manager.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", manager.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
}
|
||||
result[index] = ManagersRes{
|
||||
|
|
@ -218,7 +279,7 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /managers/{id} [get]
|
||||
// @Router /api/v1/managers/{id} [get]
|
||||
func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
|
@ -226,11 +287,22 @@ func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
|||
|
||||
// Only Super Admin / Admin / Branch Manager can view this route
|
||||
if role != domain.RoleSuperAdmin && role != domain.RoleAdmin && role != domain.RoleBranchManager {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Role Unauthorized")
|
||||
h.mongoLoggerSvc.Warn("Attempt to access from unauthorized role",
|
||||
zap.Int64("userID", requestUserID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "This role cannot view this route")
|
||||
}
|
||||
|
||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
|
||||
h.mongoLoggerSvc.Error("Cannot get company ID in context",
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID in context")
|
||||
}
|
||||
|
||||
userIDstr := c.Params("id")
|
||||
|
|
@ -241,24 +313,47 @@ func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
|||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get managers")
|
||||
h.mongoLoggerSvc.Error("Failed to get manager by id",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get managers:"+err.Error())
|
||||
}
|
||||
|
||||
// A Branch Manager can only fetch his own branch info
|
||||
if role == domain.RoleBranchManager && user.ID != requestUserID {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "User Access Not Allowed")
|
||||
h.mongoLoggerSvc.Warn("Attempt to access another branch manager info",
|
||||
zap.String("userID", userIDstr),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "User Access Not Allowed")
|
||||
}
|
||||
|
||||
// Check that only admin from company can view this route
|
||||
if role != domain.RoleSuperAdmin && user.CompanyID.Value != companyId.Value {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Only company user can view manager info")
|
||||
h.mongoLoggerSvc.Warn("Attempt to access info from another company",
|
||||
zap.String("userID", userIDstr),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Cannot access another company information")
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -301,13 +396,14 @@ type updateManagerReq struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /managers/{id} [put]
|
||||
// @Router /api/v1/managers/{id} [put]
|
||||
func (h *Handler) UpdateManagers(c *fiber.Ctx) error {
|
||||
|
||||
var req updateManagerReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("UpdateManagers failed", "error", err)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
||||
|
|
@ -14,6 +16,7 @@ import (
|
|||
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/valyala/fasthttp/fasthttpadaptor"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func hijackHTTP(c *fiber.Ctx) (net.Conn, http.ResponseWriter, error) {
|
||||
|
|
@ -45,30 +48,49 @@ func hijackHTTP(c *fiber.Ctx) (net.Conn, http.ResponseWriter, error) {
|
|||
func (h *Handler) ConnectSocket(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
}
|
||||
|
||||
// Convert *fiber.Ctx to *http.Request
|
||||
req, err := adaptor.ConvertRequest(c, false)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to convert request", "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to convert socket request",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to convert request")
|
||||
}
|
||||
|
||||
// Create a net.Conn hijacked from the fasthttp context
|
||||
netConn, rw, err := hijackHTTP(c)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to hijack connection", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to hijack connection")
|
||||
h.mongoLoggerSvc.Error("Failed to hijack connection",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to hijack connection:"+err.Error())
|
||||
}
|
||||
|
||||
// Upgrade the connection using Gorilla's Upgrader
|
||||
conn, err := ws.Upgrader.Upgrade(rw, req, nil)
|
||||
if err != nil {
|
||||
h.logger.Error("WebSocket upgrade failed", "error", err)
|
||||
h.mongoLoggerSvc.Error("WebSocket upgrade failed",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
netConn.Close()
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "WebSocket upgrade failed")
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "WebSocket upgrade failed:"+err.Error())
|
||||
}
|
||||
|
||||
client := &ws.Client{
|
||||
|
|
@ -88,9 +110,19 @@ func (h *Handler) ConnectSocket(c *fiber.Ctx) error {
|
|||
_, _, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
|
||||
h.logger.Info("WebSocket closed normally", "userID", userID)
|
||||
h.mongoLoggerSvc.Info("WebSocket closed normally",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
} else {
|
||||
h.logger.Warn("Unexpected WebSocket closure", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Warn("Unexpected WebSocket closure",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
@ -106,20 +138,34 @@ func (h *Handler) MarkNotificationAsRead(c *fiber.Ctx) error {
|
|||
|
||||
var req Request
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse request body", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to parse request body",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "invalid user identification")
|
||||
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "invalid user ID in context")
|
||||
}
|
||||
|
||||
fmt.Printf("Notification IDs: %v \n", req.NotificationIDs)
|
||||
if err := h.notificationSvc.MarkAsRead(context.Background(), req.NotificationIDs, userID); err != nil {
|
||||
h.logger.Error("Failed to mark notifications as read", "notificationID", req.NotificationIDs, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update notification status")
|
||||
h.mongoLoggerSvc.Error("Failed to mark notifications as read",
|
||||
zap.String("notificationID", strings.Join(req.NotificationIDs, ",")),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update notification status:", err.Error())
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{"message": "Notification marked as read"})
|
||||
|
|
@ -141,7 +187,11 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
|||
|
||||
var req Request
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Failed to parse request body", "error", err)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.CreateAndSendNotification] Failed to parse request body",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
|
|
@ -174,11 +224,20 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.notificationSvc.SendNotification(context.Background(), notification); err != nil {
|
||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Failed to send single notification", "recipientID", req.RecipientID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send notification")
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Failed to send single notification",
|
||||
zap.Int64("recipientID", req.RecipientID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send notification:"+err.Error())
|
||||
}
|
||||
|
||||
h.logger.Info("[NotificationSvc.CreateAndSendNotification] Single notification sent successfully", "recipientID", req.RecipientID, "type", req.Type)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.CreateAndSendNotification] Single notification sent successfully",
|
||||
zap.Int64("recipientID", req.RecipientID),
|
||||
zap.String("type", string(req.Type)),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"message": "Single notification sent successfully", "notification_id": notification.ID})
|
||||
|
||||
case domain.NotificationDeliverySchemeBulk:
|
||||
|
|
@ -186,12 +245,16 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
|||
Role: string(req.Reciever),
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Failed to fetch recipients for bulk notification", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch recipients")
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Failed to fetch recipients for bulk notification",
|
||||
zap.Int64("RecipientID", req.RecipientID),
|
||||
zap.String("Reciever", string(req.Reciever)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch recipients:"+err.Error())
|
||||
}
|
||||
|
||||
fmt.Printf("Number of Recipients %d \n", len(recipients))
|
||||
|
||||
notificationIDs := make([]string, 0, len(recipients))
|
||||
for _, user := range recipients {
|
||||
notification := &domain.Notification{
|
||||
|
|
@ -210,13 +273,23 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.notificationSvc.SendNotification(context.Background(), notification); err != nil {
|
||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Failed to send bulk notification", "UserID", user.ID, "error", err)
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Failed to send bulk notification",
|
||||
zap.Int64("UserID", user.ID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
continue
|
||||
}
|
||||
notificationIDs = append(notificationIDs, notification.ID)
|
||||
}
|
||||
|
||||
h.logger.Info("[NotificationSvc.CreateAndSendNotification] Bulk notification sent successfully", "recipient_count", len(recipients), "type", req.Type)
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Bulk notification sent successfully",
|
||||
zap.Int("recipient_count", len(recipients)),
|
||||
zap.String("type", string(req.Type)),
|
||||
zap.Int("status_code", fiber.StatusCreated),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
|
||||
"message": "Bulk notification sent successfully",
|
||||
"recipient_count": len(recipients),
|
||||
|
|
@ -224,7 +297,11 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
|||
})
|
||||
|
||||
default:
|
||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Invalid delivery scheme", "delivery_scheme", req.DeliveryScheme)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.CreateAndSendNotification] Invalid delivery scheme",
|
||||
zap.String("delivery_scheme", string(req.DeliveryScheme)),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid delivery scheme")
|
||||
}
|
||||
}
|
||||
|
|
@ -236,25 +313,45 @@ func (h *Handler) GetNotifications(c *fiber.Ctx) error {
|
|||
// Convert limit and offset to integers
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil || limit <= 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid limit value", "error", err)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.GetNotifications] Invalid limit value",
|
||||
zap.String("limit", limitStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
|
||||
}
|
||||
offset, err := strconv.Atoi(offsetStr)
|
||||
if err != nil || offset < 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid offset value", "error", err)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.GetNotifications] Invalid offset value",
|
||||
zap.String("offset", offsetStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid offset value")
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.GetNotifications] Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||
}
|
||||
|
||||
notifications, err := h.notificationSvc.ListNotifications(context.Background(), userID, limit, offset)
|
||||
if err != nil {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications")
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications:"+err.Error())
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
|
|
@ -274,15 +371,24 @@ func (h *Handler) CountUnreadNotifications(c *fiber.Ctx) error {
|
|||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Error("NotificationSvc.GetNotifications] Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||
}
|
||||
|
||||
total, err := h.notificationSvc.CountUnreadNotifications(c.Context(), userID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("[NotificationSvc.CountUnreadNotifications] Failed to fetch unread notification count", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications")
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.CountUnreadNotifications] Failed to fetch unread notification count",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications:"+err.Error())
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
|
|
@ -297,18 +403,33 @@ func (h *Handler) GetAllNotifications(c *fiber.Ctx) error {
|
|||
// Convert limit and offset to integers
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil || limit <= 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid limit value", "error", err)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.GetNotifications] Invalid limit value",
|
||||
zap.String("limit", limitStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
|
||||
}
|
||||
page, err := strconv.Atoi(pageStr)
|
||||
if err != nil || page <= 0 {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid page value", "error", err)
|
||||
h.mongoLoggerSvc.Info("[NotificationSvc.GetNotifications] Invalid page value",
|
||||
zap.String("page", pageStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid page value")
|
||||
}
|
||||
|
||||
notifications, err := h.notificationSvc.GetAllNotifications(context.Background(), limit, ((page - 1) * limit))
|
||||
if err != nil {
|
||||
h.logger.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications", "error", err)
|
||||
h.mongoLoggerSvc.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications",
|
||||
zap.Int64("limit", int64(limit)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package handlers
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// GetALLPrematchOdds
|
||||
|
|
@ -15,12 +17,17 @@ import (
|
|||
// @Produce json
|
||||
// @Success 200 {array} domain.Odd
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /odds [get]
|
||||
// @Router /api/v1/odds [get]
|
||||
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
|
||||
|
||||
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to retrieve all prematch odds",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
|
||||
|
|
@ -38,24 +45,39 @@ func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} domain.RawOddsByMarketID
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /odds/upcoming/{upcoming_id}/market/{market_id} [get]
|
||||
// @Router /api/v1/odds/upcoming/{upcoming_id}/market/{market_id} [get]
|
||||
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
|
||||
|
||||
marketID := c.Params("market_id")
|
||||
upcomingID := c.Params("upcoming_id")
|
||||
if marketID == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Missing market_id",
|
||||
zap.String("market_id", marketID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing market_id")
|
||||
}
|
||||
|
||||
upcomingID := c.Params("upcoming_id")
|
||||
if upcomingID == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Missing upcoming_id",
|
||||
zap.String("upcoming", upcomingID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing upcoming_id")
|
||||
}
|
||||
|
||||
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
|
||||
if err != nil {
|
||||
// fmt.Printf("Failed to fetch raw odds: %v market_id:%v upcomingID:%v\n", err, marketID, upcomingID)
|
||||
h.logger.Error("Failed to get raw odds by market ID", "marketID", marketID, "upcomingID", upcomingID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get raw odds by market ID",
|
||||
zap.String("marketID", marketID),
|
||||
zap.String("upcomingID", upcomingID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
|
||||
|
|
@ -73,30 +95,52 @@ func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} domain.Odd
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /odds/upcoming/{upcoming_id} [get]
|
||||
// @Router /api/v1/odds/upcoming/{upcoming_id} [get]
|
||||
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
|
||||
|
||||
upcomingID := c.Params("upcoming_id")
|
||||
if upcomingID == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Missing upcoming_id",
|
||||
zap.String("upcoming", upcomingID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Missing upcoming_id")
|
||||
}
|
||||
|
||||
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
|
||||
if err != nil || limit <= 0 {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid limit value",
|
||||
zap.Int("limit", limit),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
|
||||
}
|
||||
|
||||
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
|
||||
if err != nil || offset < 0 {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid offset value",
|
||||
zap.Int("offset", offset),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID)
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to retrieve prematch odds",
|
||||
zap.String("upcoming", upcomingID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve prematch odds"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,33 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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"
|
||||
)
|
||||
|
||||
func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||
}
|
||||
|
||||
if err := h.referralSvc.CreateReferral(c.Context(), userID); err != nil {
|
||||
h.logger.Error("Failed to create referral", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to create referral",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create referral")
|
||||
}
|
||||
|
||||
|
|
@ -24,29 +37,54 @@ func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
|||
func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
||||
var req domain.ReferralSettingsReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse settings", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to parse settings",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate settings",
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to fetch previous referral setting", "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to fetch previous referral setting",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create referral")
|
||||
}
|
||||
|
||||
// only allow one referral setting for now
|
||||
// for future it can be multiple and be able to choose from them
|
||||
if settings != nil {
|
||||
h.logger.Error("referral setting already exists", "error", err)
|
||||
h.mongoLoggerSvc.Error("referral setting already exists",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "referral setting already exists")
|
||||
}
|
||||
|
||||
if err := h.referralSvc.CreateReferralSettings(c.Context(), req); err != nil {
|
||||
h.logger.Error("Failed to create referral setting", "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to create referral setting",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create referral")
|
||||
}
|
||||
|
||||
|
|
@ -63,23 +101,37 @@ func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
|||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Security Bearer
|
||||
// @Router /referral/stats [get]
|
||||
// @Router /api/v1/referral/stats [get]
|
||||
func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get user", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
}
|
||||
|
||||
stats, err := h.referralSvc.GetReferralStats(c.Context(), user.PhoneNumber)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get referral stats", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get referral stats",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve referral stats")
|
||||
}
|
||||
|
||||
|
|
@ -98,34 +150,60 @@ func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
|||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Security Bearer
|
||||
// @Router /referral/settings [put]
|
||||
// @Router /api/v1/referral/settings [put]
|
||||
func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Error("Failed to delete user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get user", "userID", userID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
h.mongoLoggerSvc.Error("Failed to get user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
if user.Role != domain.RoleAdmin {
|
||||
h.mongoLoggerSvc.Error("Access Forbidden",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Admin access required")
|
||||
}
|
||||
|
||||
var settings domain.ReferralSettings
|
||||
if err := c.BodyParser(&settings); err != nil {
|
||||
h.logger.Error("Failed to parse settings", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to parse settings",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
settings.UpdatedBy = user.PhoneNumber
|
||||
if err := h.referralSvc.UpdateReferralSettings(c.Context(), &settings); err != nil {
|
||||
h.logger.Error("Failed to update referral settings", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update referral settings")
|
||||
h.mongoLoggerSvc.Error("Failed to update referral settings",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Referral settings updated successfully", nil, nil)
|
||||
|
|
@ -142,7 +220,7 @@ func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error {
|
|||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Security Bearer
|
||||
// @Router /referral/settings [get]
|
||||
// @Router /api/v1/referral/settings [get]
|
||||
func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
||||
// userID, ok := c.Locals("user_id").(int64)
|
||||
// if !ok || userID == 0 {
|
||||
|
|
@ -153,18 +231,34 @@ func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
|||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get user", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
}
|
||||
|
||||
if user.Role != domain.RoleAdmin {
|
||||
h.mongoLoggerSvc.Error("Admin access required",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Admin access required")
|
||||
}
|
||||
|
||||
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get referral settings", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve referral settings")
|
||||
h.mongoLoggerSvc.Error("Failed to get referral settings",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Referral settings retrieved successfully", settings, nil)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ package handlers
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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"
|
||||
)
|
||||
|
||||
type ResultRes struct {
|
||||
|
|
@ -24,17 +26,26 @@ type ResultRes struct {
|
|||
// @Success 200 {array} ResultRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /result/{id} [get]
|
||||
// @Router /api/v1/result/{id} [get]
|
||||
func (h *Handler) GetResultsByEventID(c *fiber.Ctx) error {
|
||||
eventID := c.Params("id")
|
||||
if eventID == "" {
|
||||
h.logger.Error("Event ID is required")
|
||||
h.mongoLoggerSvc.Info("Event ID is required",
|
||||
zap.String("eventID", eventID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Event ID is required")
|
||||
}
|
||||
|
||||
results, outcomes, err := h.resultSvc.GetResultsForEvent(c.Context(), eventID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get results by Event ID", "eventID", eventID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get results by Event ID",
|
||||
zap.String("eventID", eventID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve results")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ package handlers
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"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"
|
||||
)
|
||||
|
||||
// CreateShopBet godoc
|
||||
|
|
@ -18,10 +18,10 @@ import (
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param createBet body domain.ShopBetReq true "create bet"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/bet [post]
|
||||
// @Router /api/v1/shop/bet [post]
|
||||
func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
||||
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
|
@ -30,20 +30,42 @@ func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.ShopBetReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateBetReq failed to parse request", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CreateBetReq failed to parse request",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
h.logger.Error("CreateBetReq failed v", "error", valErrs)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
shopBet, err := h.transactionSvc.CreateShopBet(c.Context(), userID, role, company_id, req)
|
||||
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to cashout bet", err, nil)
|
||||
var statusCode int
|
||||
if isBetError := h.betSvc.CheckIfBetError(err); isBetError {
|
||||
statusCode = fiber.StatusBadRequest
|
||||
} else {
|
||||
statusCode = fiber.StatusInternalServerError
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Failed to create shop bet",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", statusCode),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(statusCode, "failed to create shop bet"+err.Error())
|
||||
}
|
||||
res := domain.ConvertShopBet(shopBet)
|
||||
|
||||
|
|
@ -57,10 +79,10 @@ func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param createBet body domain.CashoutReq true "cashout bet"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/bet/{id} [get]
|
||||
// @Router /api/v1/shop/bet/{id} [get]
|
||||
func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
||||
|
||||
betIDstr := c.Params("id")
|
||||
|
|
@ -68,15 +90,25 @@ func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
|||
betID, err := strconv.ParseInt(betIDstr, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CashoutReq failed bet id is invalid", "error", nil)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "bet ID is invalid", nil, nil)
|
||||
h.mongoLoggerSvc.Info("GetShopBetByBetID failed bet id is invalid",
|
||||
zap.String("betID", betIDstr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "bet ID is invalid:"+err.Error())
|
||||
}
|
||||
|
||||
bet, err := h.transactionSvc.GetShopBetByBetID(c.Context(), betID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CashoutReq failed invalid bet id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid bet ID", err, nil)
|
||||
h.mongoLoggerSvc.Error("GetShopBetByBetID failed invalid bet id",
|
||||
zap.Int64("betID", betID),
|
||||
zap.Int("status_code", fiber.StatusNotFound),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertShopBetDetail(bet)
|
||||
|
|
@ -91,10 +123,10 @@ func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param cashoutBet body domain.CashoutReq true "cashout bet"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/bet/{id}/cashout [post]
|
||||
// @Router /api/v1/shop/bet/{id}/cashout [post]
|
||||
func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
||||
|
||||
betIDStr := c.Params("id")
|
||||
|
|
@ -102,8 +134,13 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
|||
betID, err := strconv.ParseInt(betIDStr, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CashoutReq invalid bet id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid bet id", err, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq invalid bet id",
|
||||
zap.String("betID", betIDStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet id")
|
||||
}
|
||||
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
|
@ -112,20 +149,41 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.CashoutReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CashoutReq failed to parse request", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq failed to parse request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
h.logger.Error("CashoutReq failed v", "error", valErrs)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("CashoutReq validation failed",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
transaction, err := h.transactionSvc.CashoutBet(c.Context(), betID, userID, role, req, companyID)
|
||||
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to cashout bet", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to cashout bet",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int64("betID", betID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
res := domain.ConvertShopTransaction(transaction)
|
||||
|
||||
|
|
@ -139,10 +197,10 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param cashoutBet body domain.CashoutReq true "cashout bet"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/cashout [post]
|
||||
// @Router /api/v1/shop/cashout [post]
|
||||
func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
||||
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
|
@ -151,27 +209,52 @@ func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.CashoutReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CashoutReq failed to parse request", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq failed to parse request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
h.logger.Error("CashoutReq failed v", "error", valErrs)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("CashoutReq validation failed",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("error", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
bet, err := h.transactionSvc.GetShopBetByCashoutID(c.Context(), req.CashoutID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CashoutReq failed invalid cashout id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq failed invalid cashout id",
|
||||
zap.String("CashoutID", req.CashoutID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
transaction, err := h.transactionSvc.CashoutBet(c.Context(), bet.BetID, userID, role, req, companyID)
|
||||
|
||||
if err != nil {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to cashout bet", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to cashout bet",
|
||||
zap.Int64("BetID", bet.BetID),
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
res := domain.ConvertShopTransaction(transaction)
|
||||
|
||||
|
|
@ -185,24 +268,33 @@ func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param createBet body domain.CashoutReq true "cashout bet"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/cashout/{id} [get]
|
||||
// @Router /api/v1/shop/cashout/{id} [get]
|
||||
func (h *Handler) GetShopBetByCashoutID(c *fiber.Ctx) error {
|
||||
|
||||
cashoutID := c.Params("id")
|
||||
|
||||
if cashoutID == "" {
|
||||
h.logger.Error("CashoutReq failed cashout id is required", "error", nil)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "cashout ID is required", nil, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq failed cashout id is required",
|
||||
zap.String("cashoutID", cashoutID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "cashout ID is required")
|
||||
}
|
||||
|
||||
bet, err := h.transactionSvc.GetShopBetByCashoutID(c.Context(), cashoutID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CashoutReq failed invalid cashout id", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("CashoutReq failed invalid cashout id",
|
||||
zap.String("CashoutID", cashoutID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertShopBetDetail(bet)
|
||||
|
|
@ -217,10 +309,10 @@ func (h *Handler) GetShopBetByCashoutID(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param transferToWallet body domain.ShopDepositReq true "ShopDepositReq"
|
||||
// @Success 200 {object} TransferWalletRes
|
||||
// @Success 200 {object} domain.ShopDepositRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/deposit [post]
|
||||
// @Router /api/v1/shop/deposit [post]
|
||||
func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
||||
|
||||
// Get sender ID from the cashier
|
||||
|
|
@ -230,7 +322,12 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
|||
var req domain.ShopDepositReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateTransferReq failed", "error", err)
|
||||
h.mongoLoggerSvc.Info("CreateTransferReq failed",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -240,14 +337,26 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
|||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate customer deposit",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("error", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
deposit, err := h.transactionSvc.CreateShopDeposit(c.Context(), userID, role, req)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Shop Deposit Error %v \n", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
h.mongoLoggerSvc.Info("failed to create shop deposit",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertShopDeposit(deposit)
|
||||
|
|
@ -262,10 +371,10 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
|||
// @Tags transaction
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} TransactionRes
|
||||
// @Success 200 {array} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/transaction [get]
|
||||
// @Router /api/v1/shop/transaction [get]
|
||||
func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||
// Get user_id from middleware
|
||||
// userID := c.Locals("user_id").(int64)
|
||||
|
|
@ -284,8 +393,13 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
|||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||
zap.String("createdBefore", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
|
|
@ -298,8 +412,13 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
|||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||
zap.String("createdAfter", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
|
|
@ -317,8 +436,12 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get transactions", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transactions", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to get transactions",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.ShopTransactionRes, len(transactions))
|
||||
|
|
@ -337,21 +460,31 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Transaction ID"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/transaction/{id} [get]
|
||||
// @Router /api/v1/shop/transaction/{id} [get]
|
||||
func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
||||
transactionID := c.Params("id")
|
||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid transaction ID", "transactionID", transactionID, "error", err)
|
||||
h.mongoLoggerSvc.Info("Invalid transaction ID",
|
||||
zap.String("transactionID", transactionID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
|
||||
}
|
||||
|
||||
transaction, err := h.transactionSvc.GetShopTransactionByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get transaction by ID", "transactionID", id, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get shop transaction by ID",
|
||||
zap.Int64("transactionID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve transaction")
|
||||
}
|
||||
|
||||
|
|
@ -366,31 +499,37 @@ func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Transaction ID"
|
||||
// @Success 200 {object} TransactionRes
|
||||
// @Success 200 {object} domain.ShopTransactionRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/transaction/{id}/bet [get]
|
||||
// @Router /api/v1/shop/transaction/{id}/bet [get]
|
||||
func (h *Handler) GetShopBetByTransactionID(c *fiber.Ctx) error {
|
||||
transactionID := c.Params("id")
|
||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid transaction ID", "transactionID", transactionID, "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
|
||||
h.mongoLoggerSvc.Info("Invalid transaction ID",
|
||||
zap.String("transactionID", transactionID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
transaction, err := h.transactionSvc.GetShopBetByShopTransactionID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get transaction by ID", "transactionID", id, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve transaction")
|
||||
h.mongoLoggerSvc.Error("Failed to get transaction by ID",
|
||||
zap.Int64("transactionID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
res := domain.ConvertShopBetDetail(transaction)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Shop bet retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
type UpdateTransactionVerifiedReq struct {
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
}
|
||||
|
||||
// UpdateTransactionVerified godoc
|
||||
// @Summary Updates the verified field of a transaction
|
||||
// @Description Updates the verified status of a transaction
|
||||
|
|
@ -398,11 +537,11 @@ type UpdateTransactionVerifiedReq struct {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Transaction ID"
|
||||
// @Param updateVerified body UpdateTransactionVerifiedReq true "Updates Transaction Verification"
|
||||
// @Param updateVerified body domain.UpdateTransactionVerifiedReq true "Updates Transaction Verification"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /shop/transaction/{id} [put]
|
||||
// @Router /api/v1/shop/transaction/{id} [put]
|
||||
func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
||||
transactionID := c.Params("id")
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
|
@ -412,25 +551,48 @@ func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
|||
|
||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid transaction ID", "transactionID", transactionID, "error", err)
|
||||
h.mongoLoggerSvc.Info("Invalid transaction ID",
|
||||
zap.String("transactionID", transactionID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
|
||||
}
|
||||
|
||||
var req UpdateTransactionVerifiedReq
|
||||
var req domain.UpdateTransactionVerifiedReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse UpdateTransactionVerified request", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to parse UpdateTransactionVerified request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
h.logger.Info("Update Transaction Verified", slog.Bool("verified", req.Verified))
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate UpdateTransactionVerified",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.String("errMsg", errMsg),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.transactionSvc.UpdateShopTransactionVerified(c.Context(), id, req.Verified, userID, role, companyID, branchID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update transaction verification", "transactionID", id, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to update transaction verification",
|
||||
zap.Int64("transactionID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transaction verification")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// CreateTicket godoc
|
||||
|
|
@ -19,29 +22,51 @@ import (
|
|||
// @Success 200 {object} domain.CreateTicketRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /ticket [post]
|
||||
// @Router /api/v1/ticket [post]
|
||||
func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
||||
var req domain.CreateTicketReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse CreateTicket request", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to parse CreateTicket request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate CreateTicketReq",
|
||||
zap.Any("CreateTicketReq", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("error", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
newTicket, rows, err := h.ticketSvc.CreateTicket(c.Context(), req, c.IP())
|
||||
|
||||
if err != nil {
|
||||
switch err {
|
||||
case ticket.ErrEventHasBeenRemoved, ticket.ErrTicketHasExpired,
|
||||
ticket.ErrRawOddInvalid, ticket.ErrTooManyOutcomesForTicket,
|
||||
ticket.ErrTicketAmountTooHigh, ticket.ErrTicketLimitForSingleUser,
|
||||
ticket.ErrTicketWinningTooHigh:
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
|
||||
var statusCode int
|
||||
|
||||
if isTicketError := h.ticketSvc.CheckTicketError(err); isTicketError {
|
||||
statusCode = fiber.StatusBadRequest
|
||||
} else {
|
||||
statusCode = fiber.StatusInternalServerError
|
||||
}
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
|
||||
h.mongoLoggerSvc.Error("Failed to create ticket",
|
||||
zap.Any("req", req),
|
||||
zap.Int("status_code", statusCode),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(statusCode, err.Error())
|
||||
}
|
||||
res := domain.CreateTicketRes{
|
||||
FastCode: newTicket.ID,
|
||||
|
|
@ -61,18 +86,28 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} domain.TicketRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /ticket/{id} [get]
|
||||
// @Router /api/v1/ticket/{id} [get]
|
||||
func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
|
||||
ticketID := c.Params("id")
|
||||
id, err := strconv.ParseInt(ticketID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid ticket ID", "ticketID", ticketID, "error", err)
|
||||
h.mongoLoggerSvc.Info("Invalid ticket ID",
|
||||
zap.String("ticketID", ticketID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid ticket ID")
|
||||
}
|
||||
|
||||
ticket, err := h.ticketSvc.GetTicketByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get ticket by ID", "ticketID", id, "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to get ticket by ID",
|
||||
zap.Int64("ticketID", id),
|
||||
zap.Int("status_code", fiber.StatusNotFound),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve ticket")
|
||||
}
|
||||
|
||||
|
|
@ -94,12 +129,16 @@ func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} domain.TicketRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /ticket [get]
|
||||
// @Router /api/v1/ticket [get]
|
||||
func (h *Handler) GetAllTickets(c *fiber.Ctx) error {
|
||||
|
||||
tickets, err := h.ticketSvc.GetAllTickets(c.Context())
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get tickets", "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get tickets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve tickets")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ type CreateRefillReq struct {
|
|||
// @Success 200 {object} TransferWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /transfer/wallet/{id} [get]
|
||||
// @Router /api/v1/transfer/wallet/{id} [get]
|
||||
func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
||||
|
||||
walletID := c.Params("id")
|
||||
|
|
@ -135,14 +135,24 @@ func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
|||
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
||||
h.mongoLoggerSvc.Error("Invalid wallet ID",
|
||||
zap.String("walletID", walletID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||
}
|
||||
|
||||
transfers, err := h.walletSvc.GetTransfersByWallet(c.Context(), int64(id))
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get transfers by wallet", "walletID", walletID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transfers", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get transfers by wallet",
|
||||
zap.String("walletID", walletID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
var transferResponses []TransferWalletRes
|
||||
|
|
@ -164,7 +174,7 @@ func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} TransferWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /transfer/wallet/:id [post]
|
||||
// @Router /api/v1/transfer/wallet/:id [post]
|
||||
func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
||||
|
||||
receiverIDString := c.Params("id")
|
||||
|
|
@ -172,59 +182,100 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
|||
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid wallet ID",
|
||||
zap.Int64("walletID", receiverID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||
}
|
||||
// Get sender ID from the cashier
|
||||
userID := c.Locals("user_id").(int64)
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
fmt.Printf("\n\nCompany ID: %v\n\n", companyID.Value)
|
||||
// fmt.Printf("\n\nCompany ID: %v\n\n", companyID.Value)
|
||||
|
||||
var senderID int64
|
||||
//TODO: check to make sure that the cashiers aren't transferring TO branch wallet
|
||||
switch role {
|
||||
case domain.RoleCustomer:
|
||||
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
|
||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.String("role", string(role)),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Unauthorized access")
|
||||
case domain.RoleAdmin:
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch company",
|
||||
Error: err.Error(),
|
||||
})
|
||||
// return response.WriteJSON(c, fiber.StatusInternalServerError, "Error fetching company", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to fetch company",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
senderID = company.WalletID
|
||||
h.logger.Error("Will", "userID", userID, "role", role)
|
||||
// h.logger.Error("Will", "userID", userID, "role", role)
|
||||
|
||||
case domain.RoleSuperAdmin:
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Super Admin does not have a wallet", err, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Super Admin does not have a wallet")
|
||||
case domain.RoleBranchManager:
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch Manager does not have a wallet", err, nil)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Branch Manager does not have a wallet")
|
||||
case domain.RoleCashier:
|
||||
cashierBranch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get branch", "user ID", userID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve cashier branch", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get branch by cashier",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
senderID = cashierBranch.WalletID
|
||||
default:
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Unknown Role", err, nil)
|
||||
h.mongoLoggerSvc.Error("Unknown Role",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(role)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Unknown Role")
|
||||
}
|
||||
|
||||
var req CreateTransferReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateTransferReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Error("CreateTransferReq failed to parse body",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Error("Failed to validate CreateTransferReq",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
transfer, err := h.walletSvc.TransferToWallet(c.Context(),
|
||||
|
|
@ -234,8 +285,13 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
|||
)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to transfer money to wallet", zap.Error(err))
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Transfer Failed", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to transfer money to wallet",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := convertTransfer(transfer)
|
||||
|
|
@ -243,7 +299,6 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
|
||||
}
|
||||
|
||||
|
||||
// RefillWallet godoc
|
||||
// @Summary Refill wallet
|
||||
// @Description Super Admin route to refill a wallet
|
||||
|
|
@ -254,7 +309,7 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} TransferWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /transfer/refill/:id [post]
|
||||
// @Router /api/v1/transfer/refill/:id [post]
|
||||
func (h *Handler) RefillWallet(c *fiber.Ctx) error {
|
||||
|
||||
receiverIDString := c.Params("id")
|
||||
|
|
@ -263,21 +318,42 @@ func (h *Handler) RefillWallet(c *fiber.Ctx) error {
|
|||
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
||||
h.mongoLoggerSvc.Error("Invalid wallet ID",
|
||||
zap.Int64("walletID", receiverID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||
}
|
||||
// Get sender ID from the cashier
|
||||
|
||||
var req CreateRefillReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateRefillReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
h.mongoLoggerSvc.Info("CreateRefillReq failed to parse CreateRefillReq",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate CreateRefillReq",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
|
||||
}
|
||||
|
||||
transfer, err := h.walletSvc.AddToWallet(
|
||||
|
|
@ -287,7 +363,15 @@ func (h *Handler) RefillWallet(c *fiber.Ctx) error {
|
|||
}, domain.TRANSFER_BANK, domain.PaymentDetails{}, fmt.Sprintf("Added %v to wallet directly by super-admin", req.Amount))
|
||||
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Creating Transfer Failed", err, nil)
|
||||
h.mongoLoggerSvc.Error("Creating Transfer Failed",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Float32("Amount", req.Amount),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
|
||||
}
|
||||
|
||||
res := convertTransfer(transfer)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CheckPhoneEmailExistReq struct {
|
||||
|
|
@ -32,23 +33,36 @@ type CheckPhoneEmailExistRes struct {
|
|||
// @Success 200 {object} CheckPhoneEmailExistRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/checkPhoneEmailExist [post]
|
||||
// @Router /api/v1/user/checkPhoneEmailExist [post]
|
||||
func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
||||
|
||||
var req CheckPhoneEmailExistReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse CheckPhoneEmailExist request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse CheckPhoneEmailExist request",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
emailExist, phoneExist, err := h.userSvc.CheckPhoneEmailExist(c.Context(), req.PhoneNumber, req.Email)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to check phone/email existence", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check phone/email existence")
|
||||
h.mongoLoggerSvc.Error("Failed to check phone/email existence",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check phone/email existence:"+err.Error())
|
||||
}
|
||||
|
||||
res := CheckPhoneEmailExistRes{
|
||||
|
|
@ -73,17 +87,25 @@ type RegisterCodeReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/sendRegisterCode [post]
|
||||
// @Router /api/v1/user/sendRegisterCode [post]
|
||||
func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
||||
|
||||
var req RegisterCodeReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse SendRegisterCode request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse SendRegisterCode request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
var sentTo string
|
||||
|
|
@ -99,8 +121,14 @@ func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.userSvc.SendRegisterCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||
h.logger.Error("Failed to send register code", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send register code")
|
||||
h.mongoLoggerSvc.Error("Failed to send register code",
|
||||
zap.String("Medium", string(medium)),
|
||||
zap.String("Send To", string(sentTo)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send register code:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||
|
|
@ -126,17 +154,25 @@ type RegisterUserReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/register [post]
|
||||
// @Router /api/v1/user/register [post]
|
||||
func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
||||
|
||||
var req RegisterUserReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse RegisterUser request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse RegisterUser request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
user := domain.RegisterUserReq{
|
||||
FirstName: req.FirstName,
|
||||
|
|
@ -150,7 +186,13 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
}
|
||||
medium, err := getMedium(req.Email, req.PhoneNumber)
|
||||
if err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to get medium",
|
||||
zap.String("email", req.Email),
|
||||
zap.String("phone number", req.PhoneNumber),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -170,20 +212,36 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
if errors.Is(err, domain.ErrOtpNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "User already exist")
|
||||
}
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Unknown Error")
|
||||
h.mongoLoggerSvc.Error("Failed to register user",
|
||||
zap.String("email", req.Email),
|
||||
zap.String("phone number", req.PhoneNumber),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "failed to register user:"+err.Error())
|
||||
}
|
||||
|
||||
newWallet, err := h.walletSvc.CreateCustomerWallet(c.Context(), newUser.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to create wallet for user", "userID", newUser.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet")
|
||||
h.mongoLoggerSvc.Error("Failed to create wallet for user",
|
||||
zap.Int64("userID", newUser.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet:"+err.Error())
|
||||
}
|
||||
|
||||
if req.ReferalCode != "" {
|
||||
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferalCode)
|
||||
if err != nil {
|
||||
h.logger.Warn("Failed to process referral during registration", "phone", req.PhoneNumber, "code", req.ReferalCode, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to process referral during registration",
|
||||
zap.String("phone", req.PhoneNumber),
|
||||
zap.String("code", req.ReferalCode),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,8 +251,13 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
"Added 100.0 to wallet only as test for deployment")
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update wallet for user", "userID", newUser.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user wallet")
|
||||
h.mongoLoggerSvc.Error("Failed to update wallet for user",
|
||||
zap.Int64("userID", newUser.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user wallet:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Registration successful", nil, nil)
|
||||
|
|
@ -216,17 +279,25 @@ type ResetCodeReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/sendResetCode [post]
|
||||
// @Router /api/v1/user/sendResetCode [post]
|
||||
func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
||||
|
||||
var req ResetCodeReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse SendResetCode request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse SendResetCode request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
var sentTo string
|
||||
|
|
@ -238,13 +309,24 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
|||
sentTo = req.PhoneNumber
|
||||
medium = domain.OtpMediumSms
|
||||
} else {
|
||||
h.mongoLoggerSvc.Info("Email or PhoneNumber must be provided",
|
||||
zap.String("Email", req.Email),
|
||||
zap.String("Phone Number", req.PhoneNumber),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
||||
}
|
||||
|
||||
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||
h.logger.Error("Failed to send reset code", "error", err)
|
||||
fmt.Println(err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code")
|
||||
h.mongoLoggerSvc.Error("Failed to send reset code",
|
||||
zap.String("medium", string(medium)),
|
||||
zap.String("sentTo", string(sentTo)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||
|
|
@ -267,22 +349,36 @@ type ResetPasswordReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/resetPassword [post]
|
||||
// @Router /api/v1/user/resetPassword [post]
|
||||
func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
||||
|
||||
var req ResetPasswordReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse ResetPassword request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse ResetPassword request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
medium, err := getMedium(req.Email, req.PhoneNumber)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to determine medium for ResetPassword", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to determine medium for ResetPassword",
|
||||
zap.String("Email", req.Email),
|
||||
zap.String("Phone Number", req.PhoneNumber),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -295,8 +391,13 @@ func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.userSvc.ResetPassword(c.Context(), resetReq); err != nil {
|
||||
h.logger.Error("Failed to reset password", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset password")
|
||||
h.mongoLoggerSvc.Error("Failed to reset password",
|
||||
zap.Any("userID", resetReq),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset password:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
|
||||
|
|
@ -328,26 +429,40 @@ type UserProfileRes struct {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Security Bearer
|
||||
// @Router /user/profile [get]
|
||||
// @Router /api/v1/user/profile [get]
|
||||
func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
||||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get user profile", "userID", userID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user profile")
|
||||
h.mongoLoggerSvc.Error("Failed to get user profile",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user profile:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", userID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -396,37 +511,51 @@ type SearchUserByNameOrPhoneReq struct {
|
|||
// @Success 200 {object} UserProfileRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/search [post]
|
||||
// @Router /api/v1/user/search [post]
|
||||
func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
||||
// TODO: Add filtering by role based on which user is calling this
|
||||
var req SearchUserByNameOrPhoneReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid request",
|
||||
})
|
||||
h.mongoLoggerSvc.Error("Failed to Search UserBy Name Or Phone failed",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
return nil
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
users, err := h.userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString, req.Role, companyID)
|
||||
if err != nil {
|
||||
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Internal server error",
|
||||
})
|
||||
h.mongoLoggerSvc.Error("Failed to get user by name or phone",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to get users"+err.Error())
|
||||
}
|
||||
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
|
||||
for _, user := range users {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Any("userID", user.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -462,7 +591,7 @@ func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/single/{id} [get]
|
||||
// @Router /api/v1/user/single/{id} [get]
|
||||
func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
||||
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
||||
// filter := user.Filter{
|
||||
|
|
@ -482,21 +611,36 @@ func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
|||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to fetch user using UserID", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("failed to parse user id",
|
||||
zap.String("userID", userIDstr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid user id")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Get User By ID failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Get User By ID failed",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get cashiers:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", user.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
|
|
@ -532,19 +676,29 @@ func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/delete/{id} [delete]
|
||||
// @Router /api/v1/user/delete/{id} [delete]
|
||||
func (h *Handler) DeleteUser(c *fiber.Ctx) error {
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("DeleteUser failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Failed to parse user id",
|
||||
zap.String("userID", userIDstr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
|
||||
}
|
||||
|
||||
err = h.userSvc.DeleteUser(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to delete user", "userID", userID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to delete user", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to delete user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete user:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User deleted successfully", nil, nil)
|
||||
|
|
@ -569,14 +723,17 @@ type UpdateUserSuspendRes struct {
|
|||
// @Success 200 {object} UpdateUserSuspendRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/suspend [post]
|
||||
// @Router /api/v1/user/suspend [post]
|
||||
func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
||||
var req UpdateUserSuspendReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse UpdateUserSuspend request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
h.mongoLoggerSvc.Info("Failed to parse UpdateUserSuspend request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
fmt.Printf("user suspended %v \n", req)
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
|
|
@ -587,8 +744,13 @@ func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
|||
|
||||
err := h.userSvc.UpdateUserSuspend(c.Context(), req.UserID, req.Suspended)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update user suspend status", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user suspend status")
|
||||
h.mongoLoggerSvc.Error("Failed to update user suspend status",
|
||||
zap.Any("UpdateUserSuspendReq", req),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user suspend status:"+err.Error())
|
||||
}
|
||||
|
||||
res := UpdateUserSuspendRes{
|
||||
|
|
@ -607,18 +769,27 @@ func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/bets [get]
|
||||
// @Router /api/v1/user/bets [get]
|
||||
func (h *Handler) GetBetByUserID(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||
}
|
||||
|
||||
bets, err := h.betSvc.GetBetByUserID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get bets", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets")
|
||||
h.mongoLoggerSvc.Error("Failed to get bets",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets:"+err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.BetRes, len(bets))
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"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"
|
||||
)
|
||||
|
||||
type WalletRes struct {
|
||||
|
|
@ -94,18 +96,28 @@ type BranchWalletRes struct {
|
|||
// @Success 200 {object} WalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /wallet/{id} [get]
|
||||
// @Router /api/v1/wallet/{id} [get]
|
||||
func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
|
||||
walletID := c.Params("id")
|
||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Invalid wallet ID",
|
||||
zap.String("walletID", walletID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||
}
|
||||
|
||||
wallet, err := h.walletSvc.GetWalletByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallet by ID", "walletID", id, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get wallet by ID",
|
||||
zap.Int64("walletID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet")
|
||||
}
|
||||
|
||||
|
|
@ -123,14 +135,18 @@ func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} WalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /wallet [get]
|
||||
// @Router /api/v1/wallet [get]
|
||||
func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
|
||||
|
||||
wallets, err := h.walletSvc.GetAllWallets(c.Context())
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallets", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get wallets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
var res []WalletRes = make([]WalletRes, 0, len(wallets))
|
||||
|
|
@ -152,14 +168,18 @@ func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} WalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /branchWallet [get]
|
||||
// @Router /api/v1/branchWallet [get]
|
||||
func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
||||
|
||||
wallets, err := h.walletSvc.GetAllBranchWallets(c.Context())
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallets", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get wallets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallets")
|
||||
}
|
||||
|
||||
var res []BranchWalletRes = make([]BranchWalletRes, 0, len(wallets))
|
||||
|
|
@ -191,14 +211,18 @@ func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
|||
// @Success 200 {array} CustomerWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /customerWallet [get]
|
||||
// @Router /api/v1/customerWallet [get]
|
||||
func (h *Handler) GetAllCustomerWallets(c *fiber.Ctx) error {
|
||||
|
||||
wallets, err := h.walletSvc.GetAllCustomerWallet(c.Context())
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallets", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get customer wallets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallets")
|
||||
}
|
||||
|
||||
var res []CustomerWalletRes = make([]CustomerWalletRes, 0, len(wallets))
|
||||
|
|
@ -225,29 +249,53 @@ type UpdateWalletActiveReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /wallet/{id} [patch]
|
||||
// @Router /api/v1/wallet/{id} [patch]
|
||||
func (h *Handler) UpdateWalletActive(c *fiber.Ctx) error {
|
||||
|
||||
walletID := c.Params("id")
|
||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
|
||||
h.mongoLoggerSvc.Info("Invalid wallet ID",
|
||||
zap.String("walletID", walletID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||
}
|
||||
|
||||
var req UpdateWalletActiveReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse UpdateWalletActive request", "error", err)
|
||||
h.mongoLoggerSvc.Info("Failed to parse UpdateWalletActive request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate UpdateWalletActiveReq",
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
err = h.walletSvc.UpdateWalletActive(c.Context(), id, req.IsActive)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update wallet active status", "walletID", id, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to update wallet active status",
|
||||
zap.Int64("walletID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update wallet")
|
||||
}
|
||||
|
||||
|
|
@ -265,24 +313,37 @@ func (h *Handler) UpdateWalletActive(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} CustomerWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/wallet [get]
|
||||
// @Router /api/v1/user/wallet [get]
|
||||
func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
|
||||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.logger.Error("Invalid user ID in context")
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id in context")
|
||||
}
|
||||
|
||||
role, ok := c.Locals("role").(domain.Role)
|
||||
if !ok {
|
||||
h.logger.Error("Invalid role in context", "userID", userID)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid role")
|
||||
h.mongoLoggerSvc.Error("Invalid role in context",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.String("role", string(role)),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid role")
|
||||
}
|
||||
|
||||
if role != domain.RoleCustomer {
|
||||
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Unauthorized access")
|
||||
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.String("role", string(role)),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Unauthorized access")
|
||||
}
|
||||
|
||||
// companyID, err := strconv.ParseInt(c.Get("company_id"), 10, 64)
|
||||
|
|
@ -295,7 +356,12 @@ func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
|
|||
|
||||
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get customer wallet", "userID", userID, "error", err)
|
||||
h.mongoLoggerSvc.Error("Failed to get customer wallet",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet")
|
||||
}
|
||||
|
||||
|
|
@ -315,40 +381,63 @@ func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
|
|||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashierWallet [get]
|
||||
// @Router /api/v1/cashierWallet [get]
|
||||
func (h *Handler) GetWalletForCashier(c *fiber.Ctx) error {
|
||||
cashierID, ok := c.Locals("user_id").(int64)
|
||||
|
||||
if !ok || cashierID == 0 {
|
||||
h.logger.Error("Invalid cashier ID in context")
|
||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid cashier identification", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Invalid cashier ID in context",
|
||||
zap.Int64("cashierID", cashierID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid cashier id")
|
||||
}
|
||||
|
||||
role, ok := c.Locals("role").(domain.Role)
|
||||
|
||||
if !ok || role != domain.RoleCashier {
|
||||
h.logger.Error("Unauthorized access", "cashierID", cashierID, "role", role)
|
||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
|
||||
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||
zap.Int64("cashierID", cashierID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.String("role", string(role)),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Unauthorized access")
|
||||
}
|
||||
|
||||
branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
|
||||
if !ok || !branchID.Valid {
|
||||
h.logger.Error("Invalid branch ID in context", "cashierID", cashierID)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", nil, nil)
|
||||
h.mongoLoggerSvc.Info("Invalid branch ID in context",
|
||||
zap.Int64("cashierID", cashierID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
|
||||
}
|
||||
|
||||
branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get branch by ID", "branchID", branchID.Value, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get branch by ID",
|
||||
zap.Int64("branchID", branchID.Value),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
wallet, err := h.walletSvc.GetWalletByID(c.Context(), branch.WalletID)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallet for cashier", "cashierID", cashierID, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallet", err, nil)
|
||||
h.mongoLoggerSvc.Error("Failed to get wallet for cashier",
|
||||
zap.Int64("cashierID", cashierID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := WalletRes{
|
||||
|
|
|
|||
|
|
@ -4,22 +4,38 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (a *App) authMiddleware(c *fiber.Ctx) error {
|
||||
|
||||
ip := c.IP()
|
||||
userAgent := c.Get("User-Agent")
|
||||
c.Locals("ip_address", ip)
|
||||
c.Locals("user_agent", userAgent)
|
||||
authHeader := c.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
// fmt.Println("Auth Header Missing")
|
||||
a.mongoLoggerSvc.Info("Authorization header missing",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Authorization header missing")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
||||
fmt.Println("Invalid authorization header format")
|
||||
a.mongoLoggerSvc.Info("Invalid authorization header format",
|
||||
zap.String("authHeader", authHeader),
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid authorization header format")
|
||||
}
|
||||
|
||||
|
|
@ -28,10 +44,20 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
claim, err := jwtutil.ParseJwt(accessToken, a.JwtConfig.JwtAccessKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, jwtutil.ErrExpiredToken) {
|
||||
fmt.Println("Token Expired")
|
||||
a.mongoLoggerSvc.Info("Access Token Expired",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Access token expired")
|
||||
}
|
||||
fmt.Println("Invalid Token")
|
||||
a.mongoLoggerSvc.Info("Invalid Access Token",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +70,12 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
}
|
||||
// Asserting to make sure that there is no company role without a valid company id
|
||||
if claim.Role != domain.RoleSuperAdmin && claim.Role != domain.RoleCustomer && !claim.CompanyID.Valid {
|
||||
fmt.Println("Company Role without Company ID")
|
||||
a.mongoLoggerSvc.Error("Company Role without Company ID",
|
||||
zap.Int64("userID", claim.UserId),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Company Role without Company ID")
|
||||
}
|
||||
c.Locals("user_id", claim.UserId)
|
||||
|
|
@ -57,8 +88,13 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
if claim.Role == domain.RoleCashier {
|
||||
branch, err := a.branchSvc.GetBranchByCashier(c.Context(), claim.UserId)
|
||||
if err != nil {
|
||||
a.logger.Error("Failed to get branch id for bet", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to branch id for bet")
|
||||
a.mongoLoggerSvc.Error("Failed to get branch id for cashier",
|
||||
zap.Int64("userID", claim.UserId),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to branch id for cashier")
|
||||
}
|
||||
branchID = domain.ValidInt64{
|
||||
Value: branch.ID,
|
||||
|
|
@ -72,61 +108,116 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
func (a *App) SuperAdminOnly(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
userRole := c.Locals("role").(domain.Role)
|
||||
if userRole != domain.RoleSuperAdmin {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
a.mongoLoggerSvc.Warn("Attempt to access restricted SuperAdminOnly route",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(userRole)),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "This route is restricted")
|
||||
}
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func (a *App) CompanyOnly(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
userRole := c.Locals("role").(domain.Role)
|
||||
if userRole == domain.RoleCustomer {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
a.mongoLoggerSvc.Warn("Attempt to access restricted CompanyOnly route",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(userRole)),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "This route is restricted")
|
||||
}
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func (a *App) OnlyAdminAndAbove(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
userRole := c.Locals("role").(domain.Role)
|
||||
if userRole != domain.RoleSuperAdmin && userRole != domain.RoleAdmin {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
a.mongoLoggerSvc.Warn("Attempt to access restricted OnlyAdminAndAbove route",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(userRole)),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "This route is restricted")
|
||||
}
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func (a *App) OnlyBranchManagerAndAbove(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
userRole := c.Locals("role").(domain.Role)
|
||||
if userRole != domain.RoleSuperAdmin && userRole != domain.RoleAdmin && userRole != domain.RoleBranchManager {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
a.mongoLoggerSvc.Warn("Attempt to access restricted OnlyBranchMangerAndAbove route",
|
||||
zap.Int64("userID", userID),
|
||||
zap.String("role", string(userRole)),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "This route is restricted")
|
||||
}
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func (a *App) WebsocketAuthMiddleware(c *fiber.Ctx) error {
|
||||
tokenStr := c.Query("token")
|
||||
ip := c.IP()
|
||||
userAgent := c.Get("User-Agent")
|
||||
|
||||
if tokenStr == "" {
|
||||
a.logger.Error("Missing token in query parameter")
|
||||
a.mongoLoggerSvc.Info("Missing token in query parameter",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Missing token")
|
||||
}
|
||||
|
||||
claim, err := jwtutil.ParseJwt(tokenStr, a.JwtConfig.JwtAccessKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, jwtutil.ErrExpiredToken) {
|
||||
a.logger.Error("Token expired")
|
||||
a.mongoLoggerSvc.Info("Token expired",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Token expired")
|
||||
}
|
||||
a.logger.Error("Invalid token", "error", err)
|
||||
a.mongoLoggerSvc.Info("Invalid token",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid token")
|
||||
}
|
||||
|
||||
userID := claim.UserId
|
||||
if userID == 0 {
|
||||
a.logger.Error("Invalid user ID in token claims")
|
||||
a.mongoLoggerSvc.Info("Invalid user ID in token claims",
|
||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
||||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
|
||||
}
|
||||
|
||||
c.Locals("userID", userID)
|
||||
a.logger.Info("Authenticated WebSocket connection", "userID", userID)
|
||||
a.mongoLoggerSvc.Info("Authenticated WebSocket connection",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return c.Next()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,26 +52,27 @@ func (a *App) initAppRoutes() {
|
|||
a.mongoLoggerSvc,
|
||||
)
|
||||
|
||||
group := a.fiber.Group("/api/v1")
|
||||
|
||||
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Welcome to the FortuneBet API",
|
||||
"version": "1.0dev8.5",
|
||||
"version": "1.0dev10",
|
||||
})
|
||||
})
|
||||
// Swagger
|
||||
a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())
|
||||
|
||||
group.Get("/", func(c *fiber.Ctx) error {
|
||||
groupV1 := a.fiber.Group("/api/v1")
|
||||
groupV1.Get("/", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "FortuneBet API V1 pre-alpha",
|
||||
"version": "1.0dev9",
|
||||
"version": "1.0dev10",
|
||||
})
|
||||
})
|
||||
// Auth Routes
|
||||
a.fiber.Post("/auth/login", h.LoginCustomer)
|
||||
a.fiber.Post("/auth/refresh", h.RefreshToken)
|
||||
a.fiber.Post("/auth/logout", a.authMiddleware, h.LogOutCustomer)
|
||||
a.fiber.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
|
||||
groupV1.Post("/auth/login", h.LoginCustomer)
|
||||
groupV1.Post("/auth/refresh", h.RefreshToken)
|
||||
groupV1.Post("/auth/logout", a.authMiddleware, h.LogOutCustomer)
|
||||
groupV1.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
|
||||
|
|
@ -98,149 +99,146 @@ func (a *App) initAppRoutes() {
|
|||
})
|
||||
|
||||
// User Routes
|
||||
a.fiber.Post("/user/resetPassword", h.ResetPassword)
|
||||
a.fiber.Post("/user/sendResetCode", h.SendResetCode)
|
||||
a.fiber.Post("/user/register", h.RegisterUser)
|
||||
a.fiber.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
||||
a.fiber.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
||||
a.fiber.Get("/user/profile", a.authMiddleware, h.UserProfile)
|
||||
a.fiber.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
||||
a.fiber.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
|
||||
a.fiber.Post("/user/suspend", a.authMiddleware, h.UpdateUserSuspend)
|
||||
a.fiber.Get("/user/ress", a.authMiddleware, h.GetBetByUserID)
|
||||
groupV1.Post("/user/resetPassword", h.ResetPassword)
|
||||
groupV1.Post("/user/sendResetCode", h.SendResetCode)
|
||||
groupV1.Post("/user/register", h.RegisterUser)
|
||||
groupV1.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
||||
groupV1.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
||||
groupV1.Get("/user/profile", a.authMiddleware, h.UserProfile)
|
||||
groupV1.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
||||
groupV1.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
|
||||
groupV1.Post("/user/suspend", a.authMiddleware, h.UpdateUserSuspend)
|
||||
groupV1.Get("/user/bets", a.authMiddleware, h.GetBetByUserID)
|
||||
|
||||
a.fiber.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||
a.fiber.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||
groupV1.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||
groupV1.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||
|
||||
// Referral Routes
|
||||
a.fiber.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
||||
a.fiber.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
||||
a.fiber.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
|
||||
a.fiber.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
|
||||
a.fiber.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
|
||||
groupV1.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
||||
groupV1.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
||||
groupV1.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
|
||||
groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
|
||||
groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
|
||||
|
||||
// Bonus Routes
|
||||
a.fiber.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier)
|
||||
a.fiber.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
|
||||
a.fiber.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
|
||||
groupV1.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier)
|
||||
groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
|
||||
groupV1.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
|
||||
|
||||
a.fiber.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
|
||||
a.fiber.Get("/cashiers/:id", a.authMiddleware, h.GetCashierByID)
|
||||
a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
||||
a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
||||
groupV1.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
|
||||
groupV1.Get("/cashiers/:id", a.authMiddleware, h.GetCashierByID)
|
||||
groupV1.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
||||
groupV1.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
||||
|
||||
a.fiber.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
|
||||
a.fiber.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
|
||||
a.fiber.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
|
||||
groupV1.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
|
||||
groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
|
||||
groupV1.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
|
||||
|
||||
a.fiber.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
||||
a.fiber.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
|
||||
a.fiber.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
||||
a.fiber.Put("/admin/:id", a.authMiddleware, h.UpdateAdmin)
|
||||
groupV1.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
||||
groupV1.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
|
||||
groupV1.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
||||
groupV1.Put("/admin/:id", a.authMiddleware, h.UpdateAdmin)
|
||||
|
||||
a.fiber.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
||||
a.fiber.Get("/managers/:id", a.authMiddleware, h.GetManagerByID)
|
||||
a.fiber.Post("/managers", a.authMiddleware, h.CreateManager)
|
||||
a.fiber.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
|
||||
a.fiber.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
|
||||
groupV1.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
||||
groupV1.Get("/managers/:id", a.authMiddleware, h.GetManagerByID)
|
||||
groupV1.Post("/managers", a.authMiddleware, h.CreateManager)
|
||||
groupV1.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
|
||||
groupV1.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
|
||||
|
||||
a.fiber.Get("/odds", h.GetALLPrematchOdds)
|
||||
a.fiber.Get("/odds/upcoming/:upcoming_id", h.GetOddsByUpcomingID)
|
||||
a.fiber.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
|
||||
groupV1.Get("/odds", h.GetALLPrematchOdds)
|
||||
groupV1.Get("/odds/upcoming/:upcoming_id", h.GetOddsByUpcomingID)
|
||||
groupV1.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
|
||||
|
||||
a.fiber.Get("/events", h.GetAllUpcomingEvents)
|
||||
a.fiber.Get("/events/:id", h.GetUpcomingEventByID)
|
||||
a.fiber.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
|
||||
a.fiber.Get("/top-leagues", h.GetTopLeagues)
|
||||
a.fiber.Get("/events/:id/flag", h.UpdateEventFlagged)
|
||||
groupV1.Get("/events", h.GetAllUpcomingEvents)
|
||||
groupV1.Get("/events/:id", h.GetUpcomingEventByID)
|
||||
groupV1.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
|
||||
groupV1.Get("/top-leagues", h.GetTopLeagues)
|
||||
groupV1.Get("/events/:id/flag", h.UpdateEventFlagged)
|
||||
|
||||
// Leagues
|
||||
a.fiber.Get("/leagues", h.GetAllLeagues)
|
||||
a.fiber.Put("/leagues/:id/set-active", h.SetLeagueActive)
|
||||
groupV1.Get("/leagues", h.GetAllLeagues)
|
||||
groupV1.Put("/leagues/:id/set-active", h.SetLeagueActive)
|
||||
groupV1.Put("/leagues/:id/featured", h.SetLeagueFeatured)
|
||||
|
||||
a.fiber.Get("/result/:id", h.GetResultsByEventID)
|
||||
|
||||
// Swagger
|
||||
a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())
|
||||
groupV1.Get("/result/:id", h.GetResultsByEventID)
|
||||
|
||||
// Branch
|
||||
a.fiber.Post("/branch", a.authMiddleware, h.CreateBranch)
|
||||
a.fiber.Get("/branch", a.authMiddleware, h.GetAllBranches)
|
||||
a.fiber.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
|
||||
a.fiber.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
|
||||
a.fiber.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
|
||||
a.fiber.Put("/branch/:id/set-active", a.authMiddleware, h.UpdateBranchStatus)
|
||||
a.fiber.Put("/branch/:id/set-inactive", a.authMiddleware, h.UpdateBranchStatus)
|
||||
a.fiber.Delete("/branch/:id", a.authMiddleware, h.DeleteBranch)
|
||||
a.fiber.Get("/search/branch", a.authMiddleware, h.SearchBranch)
|
||||
groupV1.Post("/branch", a.authMiddleware, h.CreateBranch)
|
||||
groupV1.Get("/branch", a.authMiddleware, h.GetAllBranches)
|
||||
groupV1.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
|
||||
groupV1.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
|
||||
groupV1.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
|
||||
groupV1.Put("/branch/:id/set-active", a.authMiddleware, h.UpdateBranchStatus)
|
||||
groupV1.Put("/branch/:id/set-inactive", a.authMiddleware, h.UpdateBranchStatus)
|
||||
groupV1.Delete("/branch/:id", a.authMiddleware, h.DeleteBranch)
|
||||
groupV1.Get("/search/branch", a.authMiddleware, h.SearchBranch)
|
||||
// /branch/search
|
||||
// branch/wallet
|
||||
a.fiber.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers)
|
||||
a.fiber.Get("/branchCashier", a.authMiddleware, h.GetBranchForCashier)
|
||||
groupV1.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers)
|
||||
groupV1.Get("/branchCashier", a.authMiddleware, h.GetBranchForCashier)
|
||||
|
||||
// Branch Operation
|
||||
a.fiber.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
|
||||
a.fiber.Post("/supportedOperation", a.authMiddleware, h.CreateSupportedOperation)
|
||||
a.fiber.Post("/operation", a.authMiddleware, h.CreateBranchOperation)
|
||||
a.fiber.Get("/branch/:id/operation", a.authMiddleware, h.GetBranchOperations)
|
||||
groupV1.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
|
||||
groupV1.Post("/supportedOperation", a.authMiddleware, h.CreateSupportedOperation)
|
||||
groupV1.Post("/operation", a.authMiddleware, h.CreateBranchOperation)
|
||||
groupV1.Get("/branch/:id/operation", a.authMiddleware, h.GetBranchOperations)
|
||||
|
||||
a.fiber.Delete("/branch/:id/operation/:opID", a.authMiddleware, h.DeleteBranchOperation)
|
||||
groupV1.Delete("/branch/:id/operation/:opID", a.authMiddleware, h.DeleteBranchOperation)
|
||||
|
||||
// Company
|
||||
a.fiber.Post("/company", a.authMiddleware, a.SuperAdminOnly, h.CreateCompany)
|
||||
a.fiber.Get("/company", a.authMiddleware, a.SuperAdminOnly, h.GetAllCompanies)
|
||||
a.fiber.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
|
||||
a.fiber.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
|
||||
a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
||||
a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||
a.fiber.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
||||
a.fiber.Get("/admin-company", a.authMiddleware, h.GetCompanyForAdmin)
|
||||
groupV1.Post("/company", a.authMiddleware, a.SuperAdminOnly, h.CreateCompany)
|
||||
groupV1.Get("/company", a.authMiddleware, a.SuperAdminOnly, h.GetAllCompanies)
|
||||
groupV1.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
|
||||
groupV1.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
|
||||
groupV1.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
||||
groupV1.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||
groupV1.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
||||
groupV1.Get("/admin-company", a.authMiddleware, h.GetCompanyForAdmin)
|
||||
|
||||
// Ticket Routes
|
||||
a.fiber.Post("/ticket", h.CreateTicket)
|
||||
a.fiber.Get("/ticket", h.GetAllTickets)
|
||||
a.fiber.Get("/ticket/:id", h.GetTicketByID)
|
||||
groupV1.Post("/ticket", h.CreateTicket)
|
||||
groupV1.Get("/ticket", h.GetAllTickets)
|
||||
groupV1.Get("/ticket/:id", h.GetTicketByID)
|
||||
|
||||
// Bet Routes
|
||||
a.fiber.Post("/sport/bet", a.authMiddleware, h.CreateBet)
|
||||
a.fiber.Post("/sport/bet/fastcode", a.authMiddleware, h.CreateBetWithFastCode)
|
||||
a.fiber.Get("/sport/bet", a.authMiddleware, h.GetAllBet)
|
||||
a.fiber.Get("/sport/bet/:id", h.GetBetByID)
|
||||
a.fiber.Get("/sport/bet/cashout/:id", a.authMiddleware, h.GetBetByCashoutID)
|
||||
a.fiber.Patch("/sport/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
||||
a.fiber.Delete("/sport/bet/:id", a.authMiddleware, h.DeleteBet)
|
||||
groupV1.Post("/sport/bet", a.authMiddleware, h.CreateBet)
|
||||
groupV1.Post("/sport/bet/fastcode", a.authMiddleware, h.CreateBetWithFastCode)
|
||||
groupV1.Get("/sport/bet", a.authMiddleware, h.GetAllBet)
|
||||
groupV1.Get("/sport/bet/:id", h.GetBetByID)
|
||||
groupV1.Patch("/sport/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
||||
groupV1.Delete("/sport/bet/:id", a.authMiddleware, h.DeleteBet)
|
||||
|
||||
a.fiber.Post("/sport/random/bet", a.authMiddleware, h.RandomBet)
|
||||
groupV1.Post("/sport/random/bet", a.authMiddleware, h.RandomBet)
|
||||
|
||||
// Wallet
|
||||
a.fiber.Get("/wallet", h.GetAllWallets)
|
||||
a.fiber.Get("/wallet/:id", h.GetWalletByID)
|
||||
a.fiber.Put("/wallet/:id", h.UpdateWalletActive)
|
||||
a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
|
||||
a.fiber.Get("/customerWallet", a.authMiddleware, h.GetAllCustomerWallets)
|
||||
a.fiber.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
|
||||
groupV1.Get("/wallet", h.GetAllWallets)
|
||||
groupV1.Get("/wallet/:id", h.GetWalletByID)
|
||||
groupV1.Put("/wallet/:id", h.UpdateWalletActive)
|
||||
groupV1.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
|
||||
groupV1.Get("/customerWallet", a.authMiddleware, h.GetAllCustomerWallets)
|
||||
groupV1.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
|
||||
|
||||
// Transfer
|
||||
// /transfer/wallet - transfer from one wallet to another wallet
|
||||
a.fiber.Post("/transfer/wallet/:id", a.authMiddleware, h.TransferToWallet)
|
||||
a.fiber.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
|
||||
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||
groupV1.Post("/transfer/wallet/:id", a.authMiddleware, h.TransferToWallet)
|
||||
groupV1.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
|
||||
groupV1.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||
|
||||
//Chapa Routes
|
||||
group.Post("/chapa/payments/webhook/verify", h.WebhookCallback)
|
||||
group.Get("/chapa/payments/manual/verify/:tx_ref", h.ManualVerifyTransaction)
|
||||
group.Post("/chapa/payments/deposit", a.authMiddleware, h.InitiateDeposit)
|
||||
group.Post("/chapa/payments/withdraw", a.authMiddleware, h.InitiateWithdrawal)
|
||||
group.Get("/chapa/banks", h.GetSupportedBanks)
|
||||
a.fiber.Post("/chapa/payments/webhook/verify", h.WebhookCallback)
|
||||
a.fiber.Get("/chapa/payments/manual/verify/:tx_ref", h.ManualVerifyTransaction)
|
||||
a.fiber.Post("/chapa/payments/deposit", a.authMiddleware, h.InitiateDeposit)
|
||||
a.fiber.Post("/chapa/payments/withdraw", a.authMiddleware, h.InitiateWithdrawal)
|
||||
a.fiber.Get("/chapa/banks", h.GetSupportedBanks)
|
||||
|
||||
// Currencies
|
||||
group.Get("/currencies", h.GetSupportedCurrencies)
|
||||
group.Get("/currencies/convert", h.ConvertCurrency)
|
||||
groupV1.Get("/currencies", h.GetSupportedCurrencies)
|
||||
groupV1.Get("/currencies/convert", h.ConvertCurrency)
|
||||
|
||||
//Report Routes
|
||||
group.Get("/reports/dashboard", h.GetDashboardReport)
|
||||
group.Get("/report-files/download/:filename", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportFile)
|
||||
group.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
||||
groupV1.Get("/reports/dashboard", h.GetDashboardReport)
|
||||
groupV1.Get("/report-files/download/:filename", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportFile)
|
||||
groupV1.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
||||
|
||||
//Wallet Monitor Service
|
||||
// group.Get("/debug/wallet-monitor/status", func(c *fiber.Ctx) error {
|
||||
|
|
@ -263,48 +261,48 @@ func (a *App) initAppRoutes() {
|
|||
// group.Get("/chapa/transfers/verify/:transfer_ref", h.VerifyTransfer)
|
||||
|
||||
//Alea Play Virtual Game Routes
|
||||
group.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
||||
group.Post("/webhooks/alea-play", a.authMiddleware, h.HandleAleaCallback)
|
||||
groupV1.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
||||
groupV1.Post("/webhooks/alea-play", a.authMiddleware, h.HandleAleaCallback)
|
||||
|
||||
//Veli Virtual Game Routes
|
||||
group.Post("/veli/providers", h.GetProviders)
|
||||
group.Post("/veli/games-list", h.GetGamesByProvider)
|
||||
group.Post("/veli/start-game", a.authMiddleware, h.StartGame)
|
||||
group.Post("/veli/start-demo-game", a.authMiddleware, h.StartDemoGame)
|
||||
groupV1.Post("/veli/providers", h.GetProviders)
|
||||
groupV1.Post("/veli/games-list", h.GetGamesByProvider)
|
||||
groupV1.Post("/veli/start-game", a.authMiddleware, h.StartGame)
|
||||
groupV1.Post("/veli/start-demo-game", a.authMiddleware, h.StartDemoGame)
|
||||
a.fiber.Post("/balance", h.GetBalance)
|
||||
// a.fiber.Post("/bet", h.PlaceBet)
|
||||
// a.fiber.Post("/win", h.RegisterWin)
|
||||
// a.fiber.Post("/cancel", h.CancelTransaction)
|
||||
group.Post("/veli/gaming-activity", h.GetGamingActivity)
|
||||
groupV1.Post("/veli/gaming-activity", h.GetGamingActivity)
|
||||
|
||||
//mongoDB logs
|
||||
ctx := context.Background()
|
||||
group.Get("/logs", a.authMiddleware, a.SuperAdminOnly, handlers.GetLogsHandler(ctx))
|
||||
groupV1.Get("/logs", a.authMiddleware, a.SuperAdminOnly, handlers.GetLogsHandler(ctx))
|
||||
|
||||
// Recommendation Routes
|
||||
// group.Get("/virtual-games/recommendations/:userID", h.GetRecommendations)
|
||||
|
||||
// Transactions /shop/transactions
|
||||
a.fiber.Post("/shop/bet", a.authMiddleware, a.CompanyOnly, h.CreateShopBet)
|
||||
a.fiber.Get("/shop/bet/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByBetID)
|
||||
a.fiber.Post("/shop/bet/:id/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||
a.fiber.Post("/shop/bet/:id/generate", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||
a.fiber.Get("/shop/cashout/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByCashoutID)
|
||||
a.fiber.Post("/shop/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutByCashoutID)
|
||||
a.fiber.Post("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||
// a.fiber.Get("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||
a.fiber.Get("/shop/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
a.fiber.Get("/shop/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
||||
a.fiber.Get("/shop/transaction/:id/bet", a.authMiddleware, h.GetShopBetByTransactionID)
|
||||
a.fiber.Put("/shop/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||
groupV1.Post("/shop/bet", a.authMiddleware, a.CompanyOnly, h.CreateShopBet)
|
||||
groupV1.Get("/shop/bet/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByBetID)
|
||||
groupV1.Post("/shop/bet/:id/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||
groupV1.Post("/shop/bet/:id/generate", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||
groupV1.Get("/shop/cashout/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByCashoutID)
|
||||
groupV1.Post("/shop/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutByCashoutID)
|
||||
groupV1.Post("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||
// groupV1.Get("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||
groupV1.Get("/shop/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
groupV1.Get("/shop/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
||||
groupV1.Get("/shop/transaction/:id/bet", a.authMiddleware, h.GetShopBetByTransactionID)
|
||||
groupV1.Put("/shop/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||
|
||||
// Notification Routes
|
||||
a.fiber.Get("/ws/connect", a.WebsocketAuthMiddleware, h.ConnectSocket)
|
||||
a.fiber.Get("/notifications", a.authMiddleware, h.GetNotifications)
|
||||
a.fiber.Get("/notifications/all", a.authMiddleware, h.GetAllNotifications)
|
||||
a.fiber.Post("/notifications/mark-as-read", a.authMiddleware, h.MarkNotificationAsRead)
|
||||
a.fiber.Get("/notifications/unread", a.authMiddleware, h.CountUnreadNotifications)
|
||||
a.fiber.Post("/notifications/create", a.authMiddleware, h.CreateAndSendNotification)
|
||||
groupV1.Get("/ws/connect", a.WebsocketAuthMiddleware, h.ConnectSocket)
|
||||
groupV1.Get("/notifications", a.authMiddleware, h.GetNotifications)
|
||||
groupV1.Get("/notifications/all", a.authMiddleware, h.GetAllNotifications)
|
||||
groupV1.Post("/notifications/mark-as-read", a.authMiddleware, h.MarkNotificationAsRead)
|
||||
groupV1.Get("/notifications/unread", a.authMiddleware, h.CountUnreadNotifications)
|
||||
groupV1.Post("/notifications/create", a.authMiddleware, h.CreateAndSendNotification)
|
||||
|
||||
// Virtual Game Routes
|
||||
a.fiber.Post("/virtual-game/launch", a.authMiddleware, h.LaunchVirtualGame)
|
||||
|
|
@ -317,21 +315,14 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Post("/tournamentWin ", h.HandleTournamentWin)
|
||||
a.fiber.Get("/popok/games", h.GetGameList)
|
||||
a.fiber.Get("/popok/games/recommend", a.authMiddleware, h.RecommendGames)
|
||||
group.Post("/virtual-game/favorites", a.authMiddleware, h.AddFavorite)
|
||||
group.Delete("/virtual-game/favorites/:gameID", a.authMiddleware, h.RemoveFavorite)
|
||||
group.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
|
||||
groupV1.Post("/virtual-game/favorites", a.authMiddleware, h.AddFavorite)
|
||||
groupV1.Delete("/virtual-game/favorites/:gameID", a.authMiddleware, h.RemoveFavorite)
|
||||
groupV1.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
|
||||
|
||||
//Issue Reporting Routes
|
||||
group.Post("/issues", a.authMiddleware, h.CreateIssue) //anyone who has logged can report a
|
||||
group.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
|
||||
group.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
||||
group.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
||||
group.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)
|
||||
groupV1.Post("/issues", a.authMiddleware, h.CreateIssue) //anyone who has logged can report a
|
||||
groupV1.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
|
||||
groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
||||
groupV1.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
||||
groupV1.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)
|
||||
}
|
||||
|
||||
///user/profile get
|
||||
// @Router /user/resetPassword [post]
|
||||
// @Router /user/sendResetCode [post]
|
||||
// @Router /user/register [post]
|
||||
// @Router /user/sendRegisterCode [post]
|
||||
// @Router /user/checkPhoneEmailExist [post]
|
||||
|
|
|
|||
2
makefile
2
makefile
|
|
@ -56,6 +56,8 @@ restore:
|
|||
restore_file:
|
||||
@echo "Restoring latest backup..."
|
||||
gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||
seed_data:
|
||||
cat db/data/seed_data.sql | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||
postgres_log:
|
||||
docker logs fortunebet-backend-postgres-1
|
||||
.PHONY: swagger
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user