Merge branch 'ticket-bet'
This commit is contained in:
commit
5614958c5b
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
|
@ -2,6 +2,10 @@
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Cashout",
|
"Cashout",
|
||||||
"narg",
|
"narg",
|
||||||
|
"notificationservice",
|
||||||
"sqlc"
|
"sqlc"
|
||||||
]
|
],
|
||||||
|
"cSpell.enabledFileTypes": {
|
||||||
|
"sql": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ func main() {
|
||||||
companySvc := company.NewService(store)
|
companySvc := company.NewService(store)
|
||||||
leagueSvc := league.New(store)
|
leagueSvc := league.New(store)
|
||||||
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
|
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
|
||||||
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, logger, domain.MongoDBLogger)
|
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, *companySvc, *settingSvc, notificationSvc, logger, domain.MongoDBLogger)
|
||||||
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
|
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
|
||||||
bonusSvc := bonus.NewService(store)
|
bonusSvc := bonus.NewService(store)
|
||||||
referalRepo := repository.NewReferralRepository(store)
|
referalRepo := repository.NewReferralRepository(store)
|
||||||
|
|
|
||||||
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;
|
||||||
|
|
@ -45,24 +45,14 @@ CREATE TABLE IF NOT EXISTS bets (
|
||||||
amount BIGINT NOT NULL,
|
amount BIGINT NOT NULL,
|
||||||
total_odds REAL NOT NULL,
|
total_odds REAL NOT NULL,
|
||||||
status INT NOT NULL,
|
status INT NOT NULL,
|
||||||
full_name VARCHAR(255) NOT NULL,
|
user_id BIGINT NOT NULL,
|
||||||
phone_number VARCHAR(255) NOT NULL,
|
|
||||||
company_id BIGINT,
|
|
||||||
branch_id BIGINT,
|
|
||||||
user_id BIGINT,
|
|
||||||
cashed_out BOOLEAN DEFAULT FALSE NOT NULL,
|
|
||||||
cashout_id VARCHAR(255) NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
is_shop_bet BOOLEAN NOT NULL,
|
is_shop_bet BOOLEAN NOT NULL,
|
||||||
|
cashed_out BOOLEAN NOT NULL DEFAULT false,
|
||||||
outcomes_hash TEXT NOT NULL,
|
outcomes_hash TEXT NOT NULL,
|
||||||
fast_code VARCHAR(10) NOT NULL,
|
fast_code VARCHAR(10) NOT NULL,
|
||||||
processed BOOLEAN DEFAULT FALSE NOT NULL,
|
processed BOOLEAN DEFAULT FALSE NOT NULL,
|
||||||
UNIQUE(cashout_id),
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
CHECK (
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
user_id IS NOT NULL
|
|
||||||
OR branch_id IS NOT NULL
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
CREATE TABLE IF NOT EXISTS tickets (
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
|
@ -217,14 +207,16 @@ CREATE TABLE IF NOT EXISTS shop_deposits (
|
||||||
CREATE TABLE IF NOT EXISTS branches (
|
CREATE TABLE IF NOT EXISTS branches (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
name VARCHAR(255) NOT NULL,
|
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,
|
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||||
wallet_id BIGINT NOT NULL,
|
wallet_id BIGINT NOT NULL,
|
||||||
branch_manager_id BIGINT NOT NULL,
|
branch_manager_id BIGINT NOT NULL,
|
||||||
company_id BIGINT NOT NULL,
|
company_id BIGINT NOT NULL,
|
||||||
is_self_owned BOOLEAN NOT NULL DEFAULT false,
|
is_self_owned BOOLEAN NOT NULL DEFAULT false,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
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 (
|
CREATE TABLE IF NOT EXISTS branch_operations (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
|
@ -239,6 +231,10 @@ CREATE TABLE IF NOT EXISTS branch_cashiers (
|
||||||
branch_id BIGINT NOT NULL,
|
branch_id BIGINT NOT NULL,
|
||||||
UNIQUE(user_id, branch_id)
|
UNIQUE(user_id, branch_id)
|
||||||
);
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS branch_locations (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
);
|
||||||
CREATE TABLE events (
|
CREATE TABLE events (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
sport_id INT,
|
sport_id INT,
|
||||||
|
|
@ -261,7 +257,8 @@ CREATE TABLE events (
|
||||||
is_live BOOLEAN,
|
is_live BOOLEAN,
|
||||||
status TEXT,
|
status TEXT,
|
||||||
fetched_at TIMESTAMP DEFAULT now(),
|
fetched_at TIMESTAMP DEFAULT now(),
|
||||||
source TEXT DEFAULT 'b365api'
|
source TEXT DEFAULT 'b365api',
|
||||||
|
flagged BOOLEAN NOT NULL DEFAULT false
|
||||||
);
|
);
|
||||||
CREATE TABLE odds (
|
CREATE TABLE odds (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
|
@ -289,6 +286,8 @@ CREATE TABLE companies (
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
admin_id BIGINT NOT NULL,
|
admin_id BIGINT NOT NULL,
|
||||||
wallet_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,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
@ -324,7 +323,7 @@ CREATE TABLE bonus (
|
||||||
CREATE VIEW companies_details AS
|
CREATE VIEW companies_details AS
|
||||||
SELECT companies.*,
|
SELECT companies.*,
|
||||||
wallets.balance,
|
wallets.balance,
|
||||||
wallets.is_active,
|
wallets.is_active as wallet_is_active,
|
||||||
users.first_name AS admin_first_name,
|
users.first_name AS admin_first_name,
|
||||||
users.last_name AS admin_last_name,
|
users.last_name AS admin_last_name,
|
||||||
users.phone_number AS admin_phone_number
|
users.phone_number AS admin_phone_number
|
||||||
|
|
@ -348,10 +347,16 @@ CREATE TABLE IF NOT EXISTS supported_operations (
|
||||||
);
|
);
|
||||||
CREATE VIEW bet_with_outcomes AS
|
CREATE VIEW bet_with_outcomes AS
|
||||||
SELECT bets.*,
|
SELECT bets.*,
|
||||||
|
CONCAT(users.first_name, ' ', users.last_name) AS full_name,
|
||||||
|
users.phone_number,
|
||||||
JSON_AGG(bet_outcomes.*) AS outcomes
|
JSON_AGG(bet_outcomes.*) AS outcomes
|
||||||
FROM bets
|
FROM bets
|
||||||
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
|
LEFT JOIN bet_outcomes ON bets.id = bet_outcomes.bet_id
|
||||||
GROUP BY bets.id;
|
LEFT JOIN users ON bets.user_id = users.id
|
||||||
|
GROUP BY bets.id,
|
||||||
|
users.first_name,
|
||||||
|
users.last_name,
|
||||||
|
users.phone_number;
|
||||||
CREATE VIEW ticket_with_outcomes AS
|
CREATE VIEW ticket_with_outcomes AS
|
||||||
SELECT tickets.*,
|
SELECT tickets.*,
|
||||||
JSON_AGG(ticket_outcomes.*) AS outcomes
|
JSON_AGG(ticket_outcomes.*) AS outcomes
|
||||||
|
|
@ -439,8 +444,7 @@ ADD CONSTRAINT unique_email UNIQUE (email),
|
||||||
ALTER TABLE refresh_tokens
|
ALTER TABLE refresh_tokens
|
||||||
ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id);
|
ADD CONSTRAINT fk_refresh_tokens_users FOREIGN KEY (user_id) REFERENCES users(id);
|
||||||
ALTER TABLE bets
|
ALTER TABLE bets
|
||||||
ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id);
|
||||||
ADD CONSTRAINT fk_bets_branches FOREIGN KEY (branch_id) REFERENCES branches(id);
|
|
||||||
ALTER TABLE wallets
|
ALTER TABLE wallets
|
||||||
ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB';
|
ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB';
|
||||||
|
|
@ -463,7 +467,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);
|
ADD CONSTRAINT fk_shop_deposit_customers FOREIGN KEY (customer_id) REFERENCES users(id);
|
||||||
ALTER TABLE branches
|
ALTER TABLE branches
|
||||||
ADD CONSTRAINT fk_branches_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id),
|
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
|
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_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;
|
ADD CONSTRAINT fk_branch_operations_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
-- Settings Initial Data
|
-- Settings Initial Data
|
||||||
INSERT INTO settings (key, value)
|
INSERT INTO settings (key, value)
|
||||||
VALUES ('max_number_of_outcomes', '30') ON CONFLICT (key) DO
|
VALUES ('max_number_of_outcomes', '30'),
|
||||||
UPDATE
|
('bet_amount_limit', '100000'),
|
||||||
SET value = EXCLUDED.value;
|
('daily_ticket_limit', '50'),
|
||||||
INSERT INTO settings (key, value)
|
('total_winnings_limit', '1000000'),
|
||||||
VALUES ('bet_amount_limit', '100000') ON CONFLICT (key) DO
|
('amount_for_bet_referral', '1000000') 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
|
UPDATE
|
||||||
SET value = EXCLUDED.value;
|
SET value = EXCLUDED.value;
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
CREATE TABLE IF NOT EXISTS reported_issues (
|
CREATE TABLE IF NOT EXISTS reported_issues (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
customer_id BIGINT NOT NULL,
|
user_id BIGINT NOT NULL REFERENCES users(id),
|
||||||
|
user_role VARCHAR(255) NOT NULL,
|
||||||
subject TEXT NOT NULL,
|
subject TEXT NOT NULL,
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL,
|
||||||
issue_type TEXT NOT NULL, -- e.g., "deposit", "withdrawal", "bet", "technical"
|
issue_type TEXT NOT NULL,
|
||||||
status TEXT NOT NULL DEFAULT 'pending', -- pending, in_progress, resolved, rejected
|
-- e.g., "deposit", "withdrawal", "bet", "technical"
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
-- pending, in_progress, resolved, rejected
|
||||||
metadata JSONB,
|
metadata JSONB,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -3,17 +3,12 @@ INSERT INTO bets (
|
||||||
amount,
|
amount,
|
||||||
total_odds,
|
total_odds,
|
||||||
status,
|
status,
|
||||||
full_name,
|
|
||||||
phone_number,
|
|
||||||
branch_id,
|
|
||||||
user_id,
|
user_id,
|
||||||
is_shop_bet,
|
is_shop_bet,
|
||||||
cashout_id,
|
|
||||||
company_id,
|
|
||||||
outcomes_hash,
|
outcomes_hash,
|
||||||
fast_code
|
fast_code
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
-- name: CreateBetOutcome :copyfrom
|
-- name: CreateBetOutcome :copyfrom
|
||||||
INSERT INTO bet_outcomes (
|
INSERT INTO bet_outcomes (
|
||||||
|
|
@ -50,14 +45,6 @@ VALUES (
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
wHERE (
|
wHERE (
|
||||||
branch_id = sqlc.narg('branch_id')
|
|
||||||
OR sqlc.narg('branch_id') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
company_id = sqlc.narg('company_id')
|
|
||||||
OR sqlc.narg('company_id') IS NULL
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
user_id = sqlc.narg('user_id')
|
user_id = sqlc.narg('user_id')
|
||||||
OR sqlc.narg('user_id') IS NULL
|
OR sqlc.narg('user_id') IS NULL
|
||||||
)
|
)
|
||||||
|
|
@ -65,6 +52,10 @@ wHERE (
|
||||||
is_shop_bet = sqlc.narg('is_shop_bet')
|
is_shop_bet = sqlc.narg('is_shop_bet')
|
||||||
OR sqlc.narg('is_shop_bet') IS NULL
|
OR sqlc.narg('is_shop_bet') IS NULL
|
||||||
)
|
)
|
||||||
|
AND (
|
||||||
|
cashed_out = sqlc.narg('cashed_out')
|
||||||
|
OR sqlc.narg('cashed_out') IS NULL
|
||||||
|
)
|
||||||
AND (
|
AND (
|
||||||
full_name ILIKE '%' || sqlc.narg('query') || '%'
|
full_name ILIKE '%' || sqlc.narg('query') || '%'
|
||||||
OR phone_number ILIKE '%' || sqlc.narg('query') || '%'
|
OR phone_number ILIKE '%' || sqlc.narg('query') || '%'
|
||||||
|
|
@ -82,14 +73,6 @@ wHERE (
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
-- name: GetBetByCashoutID :one
|
|
||||||
SELECT *
|
|
||||||
FROM bet_with_outcomes
|
|
||||||
WHERE cashout_id = $1;
|
|
||||||
-- name: GetBetByBranchID :many
|
|
||||||
SELECT *
|
|
||||||
FROM bet_with_outcomes
|
|
||||||
WHERE branch_id = $1;
|
|
||||||
-- name: GetBetByUserID :many
|
-- name: GetBetByUserID :many
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
|
|
@ -157,4 +140,4 @@ DELETE FROM bets
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
-- name: DeleteBetOutcome :exec
|
-- name: DeleteBetOutcome :exec
|
||||||
DELETE FROM bet_outcomes
|
DELETE FROM bet_outcomes
|
||||||
WHERE bet_id = $1;
|
WHERE bet_id = $1;
|
||||||
|
|
|
||||||
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 (
|
INSERT INTO companies (
|
||||||
name,
|
name,
|
||||||
admin_id,
|
admin_id,
|
||||||
wallet_id
|
wallet_id,
|
||||||
|
deducted_percentage
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3, $4)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
-- name: GetAllCompanies :many
|
-- name: GetAllCompanies :many
|
||||||
SELECT *
|
SELECT *
|
||||||
|
|
@ -36,6 +37,11 @@ WHERE name ILIKE '%' || $1 || '%';
|
||||||
UPDATE companies
|
UPDATE companies
|
||||||
SET name = COALESCE(sqlc.narg(name), name),
|
SET name = COALESCE(sqlc.narg(name), name),
|
||||||
admin_id = COALESCE(sqlc.narg(admin_id), admin_id),
|
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
|
updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
|
||||||
|
|
@ -126,45 +126,14 @@ SELECT id
|
||||||
FROM events
|
FROM events
|
||||||
WHERE is_live = true;
|
WHERE is_live = true;
|
||||||
-- name: GetAllUpcomingEvents :many
|
-- name: GetAllUpcomingEvents :many
|
||||||
SELECT id,
|
SELECT *
|
||||||
sport_id,
|
|
||||||
match_name,
|
|
||||||
home_team,
|
|
||||||
away_team,
|
|
||||||
home_team_id,
|
|
||||||
away_team_id,
|
|
||||||
home_kit_image,
|
|
||||||
away_kit_image,
|
|
||||||
league_id,
|
|
||||||
league_name,
|
|
||||||
league_cc,
|
|
||||||
start_time,
|
|
||||||
is_live,
|
|
||||||
status,
|
|
||||||
source,
|
|
||||||
fetched_at
|
|
||||||
FROM events
|
FROM events
|
||||||
WHERE start_time > now()
|
WHERE start_time > now()
|
||||||
AND is_live = false
|
AND is_live = false
|
||||||
AND status = 'upcoming'
|
AND status = 'upcoming'
|
||||||
ORDER BY start_time ASC;
|
ORDER BY start_time ASC;
|
||||||
-- name: GetExpiredUpcomingEvents :many
|
-- name: GetExpiredUpcomingEvents :many
|
||||||
SELECT events.id,
|
SELECT events.*,
|
||||||
events.sport_id,
|
|
||||||
events.match_name,
|
|
||||||
events.home_team,
|
|
||||||
events.away_team,
|
|
||||||
events.home_team_id,
|
|
||||||
events.away_team_id,
|
|
||||||
events.home_kit_image,
|
|
||||||
events.away_kit_image,
|
|
||||||
events.league_id,
|
|
||||||
events.league_name,
|
|
||||||
events.start_time,
|
|
||||||
events.is_live,
|
|
||||||
events.status,
|
|
||||||
events.source,
|
|
||||||
events.fetched_at,
|
|
||||||
leagues.country_code as league_cc
|
leagues.country_code as league_cc
|
||||||
FROM events
|
FROM events
|
||||||
LEFT JOIN leagues ON leagues.id = league_id
|
LEFT JOIN leagues ON leagues.id = league_id
|
||||||
|
|
@ -199,24 +168,13 @@ WHERE is_live = false
|
||||||
AND (
|
AND (
|
||||||
leagues.country_code = sqlc.narg('country_code')
|
leagues.country_code = sqlc.narg('country_code')
|
||||||
OR sqlc.narg('country_code') IS NULL
|
OR sqlc.narg('country_code') IS NULL
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
flagged = sqlc.narg('flagged')
|
||||||
|
OR sqlc.narg('flagged') IS NULL
|
||||||
);
|
);
|
||||||
-- name: GetPaginatedUpcomingEvents :many
|
-- name: GetPaginatedUpcomingEvents :many
|
||||||
SELECT events.id,
|
SELECT events.*,
|
||||||
events.sport_id,
|
|
||||||
events.match_name,
|
|
||||||
events.home_team,
|
|
||||||
events.away_team,
|
|
||||||
events.home_team_id,
|
|
||||||
events.away_team_id,
|
|
||||||
events.home_kit_image,
|
|
||||||
events.away_kit_image,
|
|
||||||
events.league_id,
|
|
||||||
events.league_name,
|
|
||||||
events.start_time,
|
|
||||||
events.is_live,
|
|
||||||
events.status,
|
|
||||||
events.source,
|
|
||||||
events.fetched_at,
|
|
||||||
leagues.country_code as league_cc
|
leagues.country_code as league_cc
|
||||||
FROM events
|
FROM events
|
||||||
LEFT JOIN leagues ON leagues.id = league_id
|
LEFT JOIN leagues ON leagues.id = league_id
|
||||||
|
|
@ -243,26 +201,14 @@ WHERE start_time > now()
|
||||||
leagues.country_code = sqlc.narg('country_code')
|
leagues.country_code = sqlc.narg('country_code')
|
||||||
OR sqlc.narg('country_code') IS NULL
|
OR sqlc.narg('country_code') IS NULL
|
||||||
)
|
)
|
||||||
|
AND (
|
||||||
|
flagged = sqlc.narg('flagged')
|
||||||
|
OR sqlc.narg('flagged') IS NULL
|
||||||
|
)
|
||||||
ORDER BY start_time ASC
|
ORDER BY start_time ASC
|
||||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||||
-- name: GetUpcomingByID :one
|
-- name: GetUpcomingByID :one
|
||||||
SELECT id,
|
SELECT *
|
||||||
sport_id,
|
|
||||||
match_name,
|
|
||||||
home_team,
|
|
||||||
away_team,
|
|
||||||
home_team_id,
|
|
||||||
away_team_id,
|
|
||||||
home_kit_image,
|
|
||||||
away_kit_image,
|
|
||||||
league_id,
|
|
||||||
league_name,
|
|
||||||
league_cc,
|
|
||||||
start_time,
|
|
||||||
is_live,
|
|
||||||
status,
|
|
||||||
source,
|
|
||||||
fetched_at
|
|
||||||
FROM events
|
FROM events
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
AND is_live = false
|
AND is_live = false
|
||||||
|
|
@ -271,9 +217,12 @@ LIMIT 1;
|
||||||
-- name: UpdateMatchResult :exec
|
-- name: UpdateMatchResult :exec
|
||||||
UPDATE events
|
UPDATE events
|
||||||
SET score = $1,
|
SET score = $1,
|
||||||
status = $2,
|
status = $2
|
||||||
fetched_at = NOW()
|
|
||||||
WHERE id = $3;
|
WHERE id = $3;
|
||||||
|
-- name: UpdateFlagged :exec
|
||||||
|
UPDATE events
|
||||||
|
SET flagged = $1
|
||||||
|
WHERE id = $2;
|
||||||
-- name: DeleteEvent :exec
|
-- name: DeleteEvent :exec
|
||||||
DELETE FROM events
|
DELETE FROM events
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
|
|
@ -1,32 +1,37 @@
|
||||||
-- name: CreateReportedIssue :one
|
-- name: CreateReportedIssue :one
|
||||||
INSERT INTO reported_issues (
|
INSERT INTO reported_issues (
|
||||||
customer_id, subject, description, issue_type, metadata
|
user_id,
|
||||||
) VALUES (
|
user_role,
|
||||||
$1, $2, $3, $4, $5
|
subject,
|
||||||
)
|
description,
|
||||||
|
issue_type,
|
||||||
|
metadata
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
-- name: ListReportedIssues :many
|
-- name: ListReportedIssues :many
|
||||||
SELECT * FROM reported_issues
|
SELECT *
|
||||||
|
FROM reported_issues
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $1 OFFSET $2;
|
LIMIT $1 OFFSET $2;
|
||||||
|
-- name: ListReportedIssuesByUser :many
|
||||||
-- name: ListReportedIssuesByCustomer :many
|
SELECT *
|
||||||
SELECT * FROM reported_issues
|
FROM reported_issues
|
||||||
WHERE customer_id = $1
|
WHERE user_id = $1
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $2 OFFSET $3;
|
LIMIT $2 OFFSET $3;
|
||||||
|
|
||||||
-- name: CountReportedIssues :one
|
-- name: CountReportedIssues :one
|
||||||
SELECT COUNT(*) FROM reported_issues;
|
SELECT COUNT(*)
|
||||||
|
FROM reported_issues;
|
||||||
-- name: CountReportedIssuesByCustomer :one
|
-- name: CountReportedIssuesByUser :one
|
||||||
SELECT COUNT(*) FROM reported_issues WHERE customer_id = $1;
|
SELECT COUNT(*)
|
||||||
|
FROM reported_issues
|
||||||
|
WHERE user_id = $1;
|
||||||
-- name: UpdateReportedIssueStatus :exec
|
-- name: UpdateReportedIssueStatus :exec
|
||||||
UPDATE reported_issues
|
UPDATE reported_issues
|
||||||
SET status = $2, updated_at = NOW()
|
SET status = $2,
|
||||||
|
updated_at = NOW()
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
|
|
||||||
-- name: DeleteReportedIssue :exec
|
-- name: DeleteReportedIssue :exec
|
||||||
DELETE FROM reported_issues WHERE id = $1;
|
DELETE FROM reported_issues
|
||||||
|
WHERE id = $1;
|
||||||
|
|
@ -1,44 +1,59 @@
|
||||||
-- 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,
|
|
||||||
COUNT(*) AS total_bets,
|
|
||||||
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
|
||||||
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out,
|
|
||||||
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs
|
|
||||||
FROM bets b
|
|
||||||
JOIN companies c ON b.company_id = c.id
|
|
||||||
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
|
||||||
GROUP BY b.company_id, c.name;
|
|
||||||
-- name: GetBranchWiseReport :many
|
|
||||||
SELECT
|
|
||||||
b.branch_id,
|
|
||||||
br.name AS branch_name,
|
|
||||||
br.company_id,
|
|
||||||
COUNT(*) AS total_bets,
|
|
||||||
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
|
||||||
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out,
|
|
||||||
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs
|
|
||||||
FROM bets b
|
|
||||||
JOIN branches br ON b.branch_id = br.id
|
|
||||||
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
|
||||||
GROUP BY b.branch_id, br.name, br.company_id;
|
|
||||||
|
|
||||||
|
-- name: GetCompanyWiseReport :many
|
||||||
|
SELECT b.company_id,
|
||||||
|
c.name AS company_name,
|
||||||
|
COUNT(*) AS total_bets,
|
||||||
|
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.cashed_out THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_out,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.status = 5 THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_backs
|
||||||
|
FROM shop_bet_detail b
|
||||||
|
JOIN companies c ON b.company_id = c.id
|
||||||
|
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||||
|
GROUP BY b.company_id,
|
||||||
|
c.name;
|
||||||
|
-- name: GetBranchWiseReport :many
|
||||||
|
SELECT b.branch_id,
|
||||||
|
br.name AS branch_name,
|
||||||
|
br.company_id,
|
||||||
|
COUNT(*) AS total_bets,
|
||||||
|
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.cashed_out THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_out,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.status = 5 THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_backs
|
||||||
|
FROM shop_bet_detail b
|
||||||
|
JOIN branches br ON b.branch_id = br.id
|
||||||
|
WHERE b.created_at BETWEEN sqlc.arg('from') AND sqlc.arg('to')
|
||||||
|
GROUP BY b.branch_id,
|
||||||
|
br.name,
|
||||||
|
br.company_id;
|
||||||
|
|
@ -10,4 +10,26 @@ INSERT INTO settings (key, value, updated_at)
|
||||||
VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET value = EXCLUDED.value
|
SET value = EXCLUDED.value
|
||||||
RETURNING *;
|
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;
|
||||||
9477
docs/docs.go
9477
docs/docs.go
File diff suppressed because it is too large
Load Diff
9477
docs/swagger.json
9477
docs/swagger.json
File diff suppressed because it is too large
Load Diff
4001
docs/swagger.yaml
4001
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -16,13 +16,8 @@ INSERT INTO bets (
|
||||||
amount,
|
amount,
|
||||||
total_odds,
|
total_odds,
|
||||||
status,
|
status,
|
||||||
full_name,
|
|
||||||
phone_number,
|
|
||||||
branch_id,
|
|
||||||
user_id,
|
user_id,
|
||||||
is_shop_bet,
|
is_shop_bet,
|
||||||
cashout_id,
|
|
||||||
company_id,
|
|
||||||
outcomes_hash,
|
outcomes_hash,
|
||||||
fast_code
|
fast_code
|
||||||
)
|
)
|
||||||
|
|
@ -31,18 +26,13 @@ RETURNING id, amount, total_odds, status, full_name, phone_number, company_id, b
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateBetParams struct {
|
type CreateBetParams struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
UserID int64 `json:"user_id"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
FastCode string `json:"fast_code"`
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
|
||||||
CashoutID string `json:"cashout_id"`
|
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
|
||||||
FastCode string `json:"fast_code"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, error) {
|
func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, error) {
|
||||||
|
|
@ -50,13 +40,8 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
|
||||||
arg.Amount,
|
arg.Amount,
|
||||||
arg.TotalOdds,
|
arg.TotalOdds,
|
||||||
arg.Status,
|
arg.Status,
|
||||||
arg.FullName,
|
|
||||||
arg.PhoneNumber,
|
|
||||||
arg.BranchID,
|
|
||||||
arg.UserID,
|
arg.UserID,
|
||||||
arg.IsShopBet,
|
arg.IsShopBet,
|
||||||
arg.CashoutID,
|
|
||||||
arg.CompanyID,
|
|
||||||
arg.OutcomesHash,
|
arg.OutcomesHash,
|
||||||
arg.FastCode,
|
arg.FastCode,
|
||||||
)
|
)
|
||||||
|
|
@ -66,16 +51,9 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
|
||||||
&i.Amount,
|
&i.Amount,
|
||||||
&i.TotalOdds,
|
&i.TotalOdds,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.FullName,
|
|
||||||
&i.PhoneNumber,
|
|
||||||
&i.CompanyID,
|
|
||||||
&i.BranchID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.CashedOut,
|
|
||||||
&i.CashoutID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.CashedOut,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
&i.Processed,
|
&i.Processed,
|
||||||
|
|
@ -123,41 +101,36 @@ const GetAllBets = `-- name: GetAllBets :many
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, processed, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
wHERE (
|
wHERE (
|
||||||
branch_id = $1
|
user_id = $1
|
||||||
OR $1 IS NULL
|
OR $1 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
company_id = $2
|
is_shop_bet = $2
|
||||||
OR $2 IS NULL
|
OR $2 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
user_id = $3
|
cashed_out = $3
|
||||||
OR $3 IS NULL
|
OR $3 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
is_shop_bet = $4
|
full_name ILIKE '%' || $4 || '%'
|
||||||
|
OR phone_number ILIKE '%' || $4 || '%'
|
||||||
OR $4 IS NULL
|
OR $4 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
full_name ILIKE '%' || $5 || '%'
|
created_at > $5
|
||||||
OR phone_number ILIKE '%' || $5 || '%'
|
|
||||||
OR $5 IS NULL
|
OR $5 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
AND (
|
||||||
created_at > $6
|
created_at < $6
|
||||||
OR $6 IS NULL
|
OR $6 IS NULL
|
||||||
)
|
)
|
||||||
AND (
|
|
||||||
created_at < $7
|
|
||||||
OR $7 IS NULL
|
|
||||||
)
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetAllBetsParams struct {
|
type GetAllBetsParams struct {
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
UserID pgtype.Int8 `json:"user_id"`
|
||||||
IsShopBet pgtype.Bool `json:"is_shop_bet"`
|
IsShopBet pgtype.Bool `json:"is_shop_bet"`
|
||||||
|
CashedOut pgtype.Bool `json:"cashed_out"`
|
||||||
Query pgtype.Text `json:"query"`
|
Query pgtype.Text `json:"query"`
|
||||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||||
|
|
@ -165,10 +138,9 @@ type GetAllBetsParams struct {
|
||||||
|
|
||||||
func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) {
|
func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) {
|
||||||
rows, err := q.db.Query(ctx, GetAllBets,
|
rows, err := q.db.Query(ctx, GetAllBets,
|
||||||
arg.BranchID,
|
|
||||||
arg.CompanyID,
|
|
||||||
arg.UserID,
|
arg.UserID,
|
||||||
arg.IsShopBet,
|
arg.IsShopBet,
|
||||||
|
arg.CashedOut,
|
||||||
arg.Query,
|
arg.Query,
|
||||||
arg.CreatedBefore,
|
arg.CreatedBefore,
|
||||||
arg.CreatedAfter,
|
arg.CreatedAfter,
|
||||||
|
|
@ -185,16 +157,9 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
||||||
&i.Amount,
|
&i.Amount,
|
||||||
&i.TotalOdds,
|
&i.TotalOdds,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.FullName,
|
|
||||||
&i.PhoneNumber,
|
|
||||||
&i.CompanyID,
|
|
||||||
&i.BranchID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.CashedOut,
|
|
||||||
&i.CashoutID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.CashedOut,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
&i.Processed,
|
&i.Processed,
|
||||||
|
|
@ -302,16 +267,9 @@ func (q *Queries) GetBetByFastCode(ctx context.Context, fastCode string) (BetWit
|
||||||
&i.Amount,
|
&i.Amount,
|
||||||
&i.TotalOdds,
|
&i.TotalOdds,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.FullName,
|
|
||||||
&i.PhoneNumber,
|
|
||||||
&i.CompanyID,
|
|
||||||
&i.BranchID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.CashedOut,
|
|
||||||
&i.CashoutID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.CashedOut,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
&i.Processed,
|
&i.Processed,
|
||||||
|
|
@ -334,16 +292,9 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
|
||||||
&i.Amount,
|
&i.Amount,
|
||||||
&i.TotalOdds,
|
&i.TotalOdds,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.FullName,
|
|
||||||
&i.PhoneNumber,
|
|
||||||
&i.CompanyID,
|
|
||||||
&i.BranchID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.CashedOut,
|
|
||||||
&i.CashoutID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.CashedOut,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
&i.Processed,
|
&i.Processed,
|
||||||
|
|
@ -358,7 +309,7 @@ FROM bet_with_outcomes
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]BetWithOutcome, error) {
|
func (q *Queries) GetBetByUserID(ctx context.Context, userID int64) ([]BetWithOutcome, error) {
|
||||||
rows, err := q.db.Query(ctx, GetBetByUserID, userID)
|
rows, err := q.db.Query(ctx, GetBetByUserID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -372,16 +323,9 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
&i.Amount,
|
&i.Amount,
|
||||||
&i.TotalOdds,
|
&i.TotalOdds,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.FullName,
|
|
||||||
&i.PhoneNumber,
|
|
||||||
&i.CompanyID,
|
|
||||||
&i.BranchID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.CashedOut,
|
|
||||||
&i.CashoutID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.CashedOut,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
&i.Processed,
|
&i.Processed,
|
||||||
|
|
@ -400,13 +344,14 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
const GetBetCount = `-- name: GetBetCount :one
|
const GetBetCount = `-- name: GetBetCount :one
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM bets
|
FROM bets
|
||||||
|
WHERE user_id = $1
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
AND outcomes_hash = $2
|
AND outcomes_hash = $2
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetBetCountParams struct {
|
type GetBetCountParams struct {
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetBetCount(ctx context.Context, arg GetBetCountParams) (int64, error) {
|
func (q *Queries) GetBetCount(ctx context.Context, arg GetBetCountParams) (int64, error) {
|
||||||
|
|
|
||||||
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 (
|
INSERT INTO companies (
|
||||||
name,
|
name,
|
||||||
admin_id,
|
admin_id,
|
||||||
wallet_id
|
wallet_id,
|
||||||
|
deducted_percentage
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3, $4)
|
||||||
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 CreateCompanyParams struct {
|
type CreateCompanyParams struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
AdminID int64 `json:"admin_id"`
|
AdminID int64 `json:"admin_id"`
|
||||||
WalletID int64 `json:"wallet_id"`
|
WalletID int64 `json:"wallet_id"`
|
||||||
|
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) CreateCompany(ctx context.Context, arg CreateCompanyParams) (Company, error) {
|
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
|
var i Company
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.AdminID,
|
&i.AdminID,
|
||||||
&i.WalletID,
|
&i.WalletID,
|
||||||
|
&i.DeductedPercentage,
|
||||||
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
)
|
)
|
||||||
|
|
@ -52,7 +61,7 @@ func (q *Queries) DeleteCompany(ctx context.Context, id int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetAllCompanies = `-- name: GetAllCompanies :many
|
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
|
FROM companies_details
|
||||||
WHERE (
|
WHERE (
|
||||||
name ILIKE '%' || $1 || '%'
|
name ILIKE '%' || $1 || '%'
|
||||||
|
|
@ -91,10 +100,12 @@ func (q *Queries) GetAllCompanies(ctx context.Context, arg GetAllCompaniesParams
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.AdminID,
|
&i.AdminID,
|
||||||
&i.WalletID,
|
&i.WalletID,
|
||||||
|
&i.DeductedPercentage,
|
||||||
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.Balance,
|
&i.Balance,
|
||||||
&i.IsActive,
|
&i.WalletIsActive,
|
||||||
&i.AdminFirstName,
|
&i.AdminFirstName,
|
||||||
&i.AdminLastName,
|
&i.AdminLastName,
|
||||||
&i.AdminPhoneNumber,
|
&i.AdminPhoneNumber,
|
||||||
|
|
@ -110,7 +121,7 @@ func (q *Queries) GetAllCompanies(ctx context.Context, arg GetAllCompaniesParams
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetCompanyByID = `-- name: GetCompanyByID :one
|
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
|
FROM companies_details
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -123,10 +134,12 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.AdminID,
|
&i.AdminID,
|
||||||
&i.WalletID,
|
&i.WalletID,
|
||||||
|
&i.DeductedPercentage,
|
||||||
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.Balance,
|
&i.Balance,
|
||||||
&i.IsActive,
|
&i.WalletIsActive,
|
||||||
&i.AdminFirstName,
|
&i.AdminFirstName,
|
||||||
&i.AdminLastName,
|
&i.AdminLastName,
|
||||||
&i.AdminPhoneNumber,
|
&i.AdminPhoneNumber,
|
||||||
|
|
@ -135,7 +148,7 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (CompaniesDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchCompanyByName = `-- name: SearchCompanyByName :many
|
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
|
FROM companies_details
|
||||||
WHERE name ILIKE '%' || $1 || '%'
|
WHERE name ILIKE '%' || $1 || '%'
|
||||||
`
|
`
|
||||||
|
|
@ -154,10 +167,12 @@ func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text)
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.AdminID,
|
&i.AdminID,
|
||||||
&i.WalletID,
|
&i.WalletID,
|
||||||
|
&i.DeductedPercentage,
|
||||||
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.Balance,
|
&i.Balance,
|
||||||
&i.IsActive,
|
&i.WalletIsActive,
|
||||||
&i.AdminFirstName,
|
&i.AdminFirstName,
|
||||||
&i.AdminLastName,
|
&i.AdminLastName,
|
||||||
&i.AdminPhoneNumber,
|
&i.AdminPhoneNumber,
|
||||||
|
|
@ -176,25 +191,40 @@ const UpdateCompany = `-- name: UpdateCompany :one
|
||||||
UPDATE companies
|
UPDATE companies
|
||||||
SET name = COALESCE($2, name),
|
SET name = COALESCE($2, name),
|
||||||
admin_id = COALESCE($3, admin_id),
|
admin_id = COALESCE($3, admin_id),
|
||||||
|
is_active = COALESCE($4, is_active),
|
||||||
|
deducted_percentage = COALESCE(
|
||||||
|
$5,
|
||||||
|
deducted_percentage
|
||||||
|
),
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE id = $1
|
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 {
|
type UpdateCompanyParams struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name pgtype.Text `json:"name"`
|
Name pgtype.Text `json:"name"`
|
||||||
AdminID pgtype.Int8 `json:"admin_id"`
|
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) {
|
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
|
var i Company
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.AdminID,
|
&i.AdminID,
|
||||||
&i.WalletID,
|
&i.WalletID,
|
||||||
|
&i.DeductedPercentage,
|
||||||
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,23 +22,7 @@ func (q *Queries) DeleteEvent(ctx context.Context, id string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetAllUpcomingEvents = `-- name: GetAllUpcomingEvents :many
|
const GetAllUpcomingEvents = `-- name: GetAllUpcomingEvents :many
|
||||||
SELECT id,
|
SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, league_cc, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, flagged
|
||||||
sport_id,
|
|
||||||
match_name,
|
|
||||||
home_team,
|
|
||||||
away_team,
|
|
||||||
home_team_id,
|
|
||||||
away_team_id,
|
|
||||||
home_kit_image,
|
|
||||||
away_kit_image,
|
|
||||||
league_id,
|
|
||||||
league_name,
|
|
||||||
league_cc,
|
|
||||||
start_time,
|
|
||||||
is_live,
|
|
||||||
status,
|
|
||||||
source,
|
|
||||||
fetched_at
|
|
||||||
FROM events
|
FROM events
|
||||||
WHERE start_time > now()
|
WHERE start_time > now()
|
||||||
AND is_live = false
|
AND is_live = false
|
||||||
|
|
@ -46,35 +30,15 @@ WHERE start_time > now()
|
||||||
ORDER BY start_time ASC
|
ORDER BY start_time ASC
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetAllUpcomingEventsRow struct {
|
func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]Event, error) {
|
||||||
ID string `json:"id"`
|
|
||||||
SportID pgtype.Int4 `json:"sport_id"`
|
|
||||||
MatchName pgtype.Text `json:"match_name"`
|
|
||||||
HomeTeam pgtype.Text `json:"home_team"`
|
|
||||||
AwayTeam pgtype.Text `json:"away_team"`
|
|
||||||
HomeTeamID pgtype.Int4 `json:"home_team_id"`
|
|
||||||
AwayTeamID pgtype.Int4 `json:"away_team_id"`
|
|
||||||
HomeKitImage pgtype.Text `json:"home_kit_image"`
|
|
||||||
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
|
||||||
LeagueID pgtype.Int4 `json:"league_id"`
|
|
||||||
LeagueName pgtype.Text `json:"league_name"`
|
|
||||||
LeagueCc pgtype.Text `json:"league_cc"`
|
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
|
||||||
Status pgtype.Text `json:"status"`
|
|
||||||
Source pgtype.Text `json:"source"`
|
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEventsRow, error) {
|
|
||||||
rows, err := q.db.Query(ctx, GetAllUpcomingEvents)
|
rows, err := q.db.Query(ctx, GetAllUpcomingEvents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
var items []GetAllUpcomingEventsRow
|
var items []Event
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i GetAllUpcomingEventsRow
|
var i Event
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.SportID,
|
&i.SportID,
|
||||||
|
|
@ -89,10 +53,16 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
|
||||||
&i.LeagueName,
|
&i.LeagueName,
|
||||||
&i.LeagueCc,
|
&i.LeagueCc,
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
|
&i.Score,
|
||||||
|
&i.MatchMinute,
|
||||||
|
&i.TimerStatus,
|
||||||
|
&i.AddedTime,
|
||||||
|
&i.MatchPeriod,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.Source,
|
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
|
&i.Source,
|
||||||
|
&i.Flagged,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -105,22 +75,7 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetExpiredUpcomingEvents = `-- name: GetExpiredUpcomingEvents :many
|
const GetExpiredUpcomingEvents = `-- name: GetExpiredUpcomingEvents :many
|
||||||
SELECT events.id,
|
SELECT events.id, events.sport_id, events.match_name, events.home_team, events.away_team, events.home_team_id, events.away_team_id, events.home_kit_image, events.away_kit_image, events.league_id, events.league_name, events.league_cc, events.start_time, events.score, events.match_minute, events.timer_status, events.added_time, events.match_period, events.is_live, events.status, events.fetched_at, events.source, events.flagged,
|
||||||
events.sport_id,
|
|
||||||
events.match_name,
|
|
||||||
events.home_team,
|
|
||||||
events.away_team,
|
|
||||||
events.home_team_id,
|
|
||||||
events.away_team_id,
|
|
||||||
events.home_kit_image,
|
|
||||||
events.away_kit_image,
|
|
||||||
events.league_id,
|
|
||||||
events.league_name,
|
|
||||||
events.start_time,
|
|
||||||
events.is_live,
|
|
||||||
events.status,
|
|
||||||
events.source,
|
|
||||||
events.fetched_at,
|
|
||||||
leagues.country_code as league_cc
|
leagues.country_code as league_cc
|
||||||
FROM events
|
FROM events
|
||||||
LEFT JOIN leagues ON leagues.id = league_id
|
LEFT JOIN leagues ON leagues.id = league_id
|
||||||
|
|
@ -144,12 +99,19 @@ type GetExpiredUpcomingEventsRow struct {
|
||||||
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
||||||
LeagueID pgtype.Int4 `json:"league_id"`
|
LeagueID pgtype.Int4 `json:"league_id"`
|
||||||
LeagueName pgtype.Text `json:"league_name"`
|
LeagueName pgtype.Text `json:"league_name"`
|
||||||
|
LeagueCc pgtype.Text `json:"league_cc"`
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
|
Score pgtype.Text `json:"score"`
|
||||||
|
MatchMinute pgtype.Int4 `json:"match_minute"`
|
||||||
|
TimerStatus pgtype.Text `json:"timer_status"`
|
||||||
|
AddedTime pgtype.Int4 `json:"added_time"`
|
||||||
|
MatchPeriod pgtype.Int4 `json:"match_period"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
Source pgtype.Text `json:"source"`
|
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
LeagueCc pgtype.Text `json:"league_cc"`
|
Source pgtype.Text `json:"source"`
|
||||||
|
Flagged bool `json:"flagged"`
|
||||||
|
LeagueCc_2 pgtype.Text `json:"league_cc_2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Text) ([]GetExpiredUpcomingEventsRow, error) {
|
func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Text) ([]GetExpiredUpcomingEventsRow, error) {
|
||||||
|
|
@ -173,12 +135,19 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Te
|
||||||
&i.AwayKitImage,
|
&i.AwayKitImage,
|
||||||
&i.LeagueID,
|
&i.LeagueID,
|
||||||
&i.LeagueName,
|
&i.LeagueName,
|
||||||
|
&i.LeagueCc,
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
|
&i.Score,
|
||||||
|
&i.MatchMinute,
|
||||||
|
&i.TimerStatus,
|
||||||
|
&i.AddedTime,
|
||||||
|
&i.MatchPeriod,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.Source,
|
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
&i.LeagueCc,
|
&i.Source,
|
||||||
|
&i.Flagged,
|
||||||
|
&i.LeagueCc_2,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -191,22 +160,7 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context, status pgtype.Te
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetPaginatedUpcomingEvents = `-- name: GetPaginatedUpcomingEvents :many
|
const GetPaginatedUpcomingEvents = `-- name: GetPaginatedUpcomingEvents :many
|
||||||
SELECT events.id,
|
SELECT events.id, events.sport_id, events.match_name, events.home_team, events.away_team, events.home_team_id, events.away_team_id, events.home_kit_image, events.away_kit_image, events.league_id, events.league_name, events.league_cc, events.start_time, events.score, events.match_minute, events.timer_status, events.added_time, events.match_period, events.is_live, events.status, events.fetched_at, events.source, events.flagged,
|
||||||
events.sport_id,
|
|
||||||
events.match_name,
|
|
||||||
events.home_team,
|
|
||||||
events.away_team,
|
|
||||||
events.home_team_id,
|
|
||||||
events.away_team_id,
|
|
||||||
events.home_kit_image,
|
|
||||||
events.away_kit_image,
|
|
||||||
events.league_id,
|
|
||||||
events.league_name,
|
|
||||||
events.start_time,
|
|
||||||
events.is_live,
|
|
||||||
events.status,
|
|
||||||
events.source,
|
|
||||||
events.fetched_at,
|
|
||||||
leagues.country_code as league_cc
|
leagues.country_code as league_cc
|
||||||
FROM events
|
FROM events
|
||||||
LEFT JOIN leagues ON leagues.id = league_id
|
LEFT JOIN leagues ON leagues.id = league_id
|
||||||
|
|
@ -233,8 +187,12 @@ WHERE start_time > now()
|
||||||
leagues.country_code = $5
|
leagues.country_code = $5
|
||||||
OR $5 IS NULL
|
OR $5 IS NULL
|
||||||
)
|
)
|
||||||
|
AND (
|
||||||
|
flagged = $6
|
||||||
|
OR $6 IS NULL
|
||||||
|
)
|
||||||
ORDER BY start_time ASC
|
ORDER BY start_time ASC
|
||||||
LIMIT $7 OFFSET $6
|
LIMIT $8 OFFSET $7
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetPaginatedUpcomingEventsParams struct {
|
type GetPaginatedUpcomingEventsParams struct {
|
||||||
|
|
@ -243,6 +201,7 @@ type GetPaginatedUpcomingEventsParams struct {
|
||||||
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
||||||
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
||||||
CountryCode pgtype.Text `json:"country_code"`
|
CountryCode pgtype.Text `json:"country_code"`
|
||||||
|
Flagged pgtype.Bool `json:"flagged"`
|
||||||
Offset pgtype.Int4 `json:"offset"`
|
Offset pgtype.Int4 `json:"offset"`
|
||||||
Limit pgtype.Int4 `json:"limit"`
|
Limit pgtype.Int4 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
@ -259,12 +218,19 @@ type GetPaginatedUpcomingEventsRow struct {
|
||||||
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
||||||
LeagueID pgtype.Int4 `json:"league_id"`
|
LeagueID pgtype.Int4 `json:"league_id"`
|
||||||
LeagueName pgtype.Text `json:"league_name"`
|
LeagueName pgtype.Text `json:"league_name"`
|
||||||
|
LeagueCc pgtype.Text `json:"league_cc"`
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
|
Score pgtype.Text `json:"score"`
|
||||||
|
MatchMinute pgtype.Int4 `json:"match_minute"`
|
||||||
|
TimerStatus pgtype.Text `json:"timer_status"`
|
||||||
|
AddedTime pgtype.Int4 `json:"added_time"`
|
||||||
|
MatchPeriod pgtype.Int4 `json:"match_period"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
Source pgtype.Text `json:"source"`
|
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
LeagueCc pgtype.Text `json:"league_cc"`
|
Source pgtype.Text `json:"source"`
|
||||||
|
Flagged bool `json:"flagged"`
|
||||||
|
LeagueCc_2 pgtype.Text `json:"league_cc_2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginatedUpcomingEventsParams) ([]GetPaginatedUpcomingEventsRow, error) {
|
func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginatedUpcomingEventsParams) ([]GetPaginatedUpcomingEventsRow, error) {
|
||||||
|
|
@ -274,6 +240,7 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
|
||||||
arg.LastStartTime,
|
arg.LastStartTime,
|
||||||
arg.FirstStartTime,
|
arg.FirstStartTime,
|
||||||
arg.CountryCode,
|
arg.CountryCode,
|
||||||
|
arg.Flagged,
|
||||||
arg.Offset,
|
arg.Offset,
|
||||||
arg.Limit,
|
arg.Limit,
|
||||||
)
|
)
|
||||||
|
|
@ -296,12 +263,19 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
|
||||||
&i.AwayKitImage,
|
&i.AwayKitImage,
|
||||||
&i.LeagueID,
|
&i.LeagueID,
|
||||||
&i.LeagueName,
|
&i.LeagueName,
|
||||||
|
&i.LeagueCc,
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
|
&i.Score,
|
||||||
|
&i.MatchMinute,
|
||||||
|
&i.TimerStatus,
|
||||||
|
&i.AddedTime,
|
||||||
|
&i.MatchPeriod,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.Source,
|
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
&i.LeagueCc,
|
&i.Source,
|
||||||
|
&i.Flagged,
|
||||||
|
&i.LeagueCc_2,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -339,6 +313,10 @@ WHERE is_live = false
|
||||||
leagues.country_code = $5
|
leagues.country_code = $5
|
||||||
OR $5 IS NULL
|
OR $5 IS NULL
|
||||||
)
|
)
|
||||||
|
AND (
|
||||||
|
flagged = $6
|
||||||
|
OR $6 IS NULL
|
||||||
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetTotalEventsParams struct {
|
type GetTotalEventsParams struct {
|
||||||
|
|
@ -347,6 +325,7 @@ type GetTotalEventsParams struct {
|
||||||
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
LastStartTime pgtype.Timestamp `json:"last_start_time"`
|
||||||
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
FirstStartTime pgtype.Timestamp `json:"first_start_time"`
|
||||||
CountryCode pgtype.Text `json:"country_code"`
|
CountryCode pgtype.Text `json:"country_code"`
|
||||||
|
Flagged pgtype.Bool `json:"flagged"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams) (int64, error) {
|
func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams) (int64, error) {
|
||||||
|
|
@ -356,6 +335,7 @@ func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams)
|
||||||
arg.LastStartTime,
|
arg.LastStartTime,
|
||||||
arg.FirstStartTime,
|
arg.FirstStartTime,
|
||||||
arg.CountryCode,
|
arg.CountryCode,
|
||||||
|
arg.Flagged,
|
||||||
)
|
)
|
||||||
var count int64
|
var count int64
|
||||||
err := row.Scan(&count)
|
err := row.Scan(&count)
|
||||||
|
|
@ -363,23 +343,7 @@ func (q *Queries) GetTotalEvents(ctx context.Context, arg GetTotalEventsParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetUpcomingByID = `-- name: GetUpcomingByID :one
|
const GetUpcomingByID = `-- name: GetUpcomingByID :one
|
||||||
SELECT id,
|
SELECT id, sport_id, match_name, home_team, away_team, home_team_id, away_team_id, home_kit_image, away_kit_image, league_id, league_name, league_cc, start_time, score, match_minute, timer_status, added_time, match_period, is_live, status, fetched_at, source, flagged
|
||||||
sport_id,
|
|
||||||
match_name,
|
|
||||||
home_team,
|
|
||||||
away_team,
|
|
||||||
home_team_id,
|
|
||||||
away_team_id,
|
|
||||||
home_kit_image,
|
|
||||||
away_kit_image,
|
|
||||||
league_id,
|
|
||||||
league_name,
|
|
||||||
league_cc,
|
|
||||||
start_time,
|
|
||||||
is_live,
|
|
||||||
status,
|
|
||||||
source,
|
|
||||||
fetched_at
|
|
||||||
FROM events
|
FROM events
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
AND is_live = false
|
AND is_live = false
|
||||||
|
|
@ -387,29 +351,9 @@ WHERE id = $1
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetUpcomingByIDRow struct {
|
func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (Event, error) {
|
||||||
ID string `json:"id"`
|
|
||||||
SportID pgtype.Int4 `json:"sport_id"`
|
|
||||||
MatchName pgtype.Text `json:"match_name"`
|
|
||||||
HomeTeam pgtype.Text `json:"home_team"`
|
|
||||||
AwayTeam pgtype.Text `json:"away_team"`
|
|
||||||
HomeTeamID pgtype.Int4 `json:"home_team_id"`
|
|
||||||
AwayTeamID pgtype.Int4 `json:"away_team_id"`
|
|
||||||
HomeKitImage pgtype.Text `json:"home_kit_image"`
|
|
||||||
AwayKitImage pgtype.Text `json:"away_kit_image"`
|
|
||||||
LeagueID pgtype.Int4 `json:"league_id"`
|
|
||||||
LeagueName pgtype.Text `json:"league_name"`
|
|
||||||
LeagueCc pgtype.Text `json:"league_cc"`
|
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
|
||||||
Status pgtype.Text `json:"status"`
|
|
||||||
Source pgtype.Text `json:"source"`
|
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingByIDRow, error) {
|
|
||||||
row := q.db.QueryRow(ctx, GetUpcomingByID, id)
|
row := q.db.QueryRow(ctx, GetUpcomingByID, id)
|
||||||
var i GetUpcomingByIDRow
|
var i Event
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.SportID,
|
&i.SportID,
|
||||||
|
|
@ -424,10 +368,16 @@ func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingBy
|
||||||
&i.LeagueName,
|
&i.LeagueName,
|
||||||
&i.LeagueCc,
|
&i.LeagueCc,
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
|
&i.Score,
|
||||||
|
&i.MatchMinute,
|
||||||
|
&i.TimerStatus,
|
||||||
|
&i.AddedTime,
|
||||||
|
&i.MatchPeriod,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
&i.Source,
|
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
|
&i.Source,
|
||||||
|
&i.Flagged,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
@ -673,11 +623,26 @@ func (q *Queries) ListLiveEvents(ctx context.Context) ([]string, error) {
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UpdateFlagged = `-- name: UpdateFlagged :exec
|
||||||
|
UPDATE events
|
||||||
|
SET flagged = $1
|
||||||
|
WHERE id = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateFlaggedParams struct {
|
||||||
|
Flagged bool `json:"flagged"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateFlagged(ctx context.Context, arg UpdateFlaggedParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, UpdateFlagged, arg.Flagged, arg.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const UpdateMatchResult = `-- name: UpdateMatchResult :exec
|
const UpdateMatchResult = `-- name: UpdateMatchResult :exec
|
||||||
UPDATE events
|
UPDATE events
|
||||||
SET score = $1,
|
SET score = $1,
|
||||||
status = $2,
|
status = $2
|
||||||
fetched_at = NOW()
|
|
||||||
WHERE id = $3
|
WHERE id = $3
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const CountReportedIssues = `-- name: CountReportedIssues :one
|
const CountReportedIssues = `-- name: CountReportedIssues :one
|
||||||
SELECT COUNT(*) FROM reported_issues
|
SELECT COUNT(*)
|
||||||
|
FROM reported_issues
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) {
|
func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) {
|
||||||
|
|
@ -20,12 +21,14 @@ func (q *Queries) CountReportedIssues(ctx context.Context) (int64, error) {
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const CountReportedIssuesByCustomer = `-- name: CountReportedIssuesByCustomer :one
|
const CountReportedIssuesByUser = `-- name: CountReportedIssuesByUser :one
|
||||||
SELECT COUNT(*) FROM reported_issues WHERE customer_id = $1
|
SELECT COUNT(*)
|
||||||
|
FROM reported_issues
|
||||||
|
WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error) {
|
func (q *Queries) CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error) {
|
||||||
row := q.db.QueryRow(ctx, CountReportedIssuesByCustomer, customerID)
|
row := q.db.QueryRow(ctx, CountReportedIssuesByUser, userID)
|
||||||
var count int64
|
var count int64
|
||||||
err := row.Scan(&count)
|
err := row.Scan(&count)
|
||||||
return count, err
|
return count, err
|
||||||
|
|
@ -33,15 +36,20 @@ func (q *Queries) CountReportedIssuesByCustomer(ctx context.Context, customerID
|
||||||
|
|
||||||
const CreateReportedIssue = `-- name: CreateReportedIssue :one
|
const CreateReportedIssue = `-- name: CreateReportedIssue :one
|
||||||
INSERT INTO reported_issues (
|
INSERT INTO reported_issues (
|
||||||
customer_id, subject, description, issue_type, metadata
|
user_id,
|
||||||
) VALUES (
|
user_role,
|
||||||
$1, $2, $3, $4, $5
|
subject,
|
||||||
)
|
description,
|
||||||
RETURNING id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at
|
issue_type,
|
||||||
|
metadata
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
RETURNING id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateReportedIssueParams struct {
|
type CreateReportedIssueParams struct {
|
||||||
CustomerID int64 `json:"customer_id"`
|
UserID int64 `json:"user_id"`
|
||||||
|
UserRole string `json:"user_role"`
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
IssueType string `json:"issue_type"`
|
IssueType string `json:"issue_type"`
|
||||||
|
|
@ -50,7 +58,8 @@ type CreateReportedIssueParams struct {
|
||||||
|
|
||||||
func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIssueParams) (ReportedIssue, error) {
|
func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIssueParams) (ReportedIssue, error) {
|
||||||
row := q.db.QueryRow(ctx, CreateReportedIssue,
|
row := q.db.QueryRow(ctx, CreateReportedIssue,
|
||||||
arg.CustomerID,
|
arg.UserID,
|
||||||
|
arg.UserRole,
|
||||||
arg.Subject,
|
arg.Subject,
|
||||||
arg.Description,
|
arg.Description,
|
||||||
arg.IssueType,
|
arg.IssueType,
|
||||||
|
|
@ -59,7 +68,8 @@ func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIss
|
||||||
var i ReportedIssue
|
var i ReportedIssue
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.CustomerID,
|
&i.UserID,
|
||||||
|
&i.UserRole,
|
||||||
&i.Subject,
|
&i.Subject,
|
||||||
&i.Description,
|
&i.Description,
|
||||||
&i.IssueType,
|
&i.IssueType,
|
||||||
|
|
@ -72,7 +82,8 @@ func (q *Queries) CreateReportedIssue(ctx context.Context, arg CreateReportedIss
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteReportedIssue = `-- name: DeleteReportedIssue :exec
|
const DeleteReportedIssue = `-- name: DeleteReportedIssue :exec
|
||||||
DELETE FROM reported_issues WHERE id = $1
|
DELETE FROM reported_issues
|
||||||
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error {
|
func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error {
|
||||||
|
|
@ -81,7 +92,8 @@ func (q *Queries) DeleteReportedIssue(ctx context.Context, id int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListReportedIssues = `-- name: ListReportedIssues :many
|
const ListReportedIssues = `-- name: ListReportedIssues :many
|
||||||
SELECT id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at FROM reported_issues
|
SELECT id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
|
||||||
|
FROM reported_issues
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $1 OFFSET $2
|
LIMIT $1 OFFSET $2
|
||||||
`
|
`
|
||||||
|
|
@ -102,7 +114,8 @@ func (q *Queries) ListReportedIssues(ctx context.Context, arg ListReportedIssues
|
||||||
var i ReportedIssue
|
var i ReportedIssue
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.CustomerID,
|
&i.UserID,
|
||||||
|
&i.UserRole,
|
||||||
&i.Subject,
|
&i.Subject,
|
||||||
&i.Description,
|
&i.Description,
|
||||||
&i.IssueType,
|
&i.IssueType,
|
||||||
|
|
@ -121,21 +134,22 @@ func (q *Queries) ListReportedIssues(ctx context.Context, arg ListReportedIssues
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListReportedIssuesByCustomer = `-- name: ListReportedIssuesByCustomer :many
|
const ListReportedIssuesByUser = `-- name: ListReportedIssuesByUser :many
|
||||||
SELECT id, customer_id, subject, description, issue_type, status, metadata, created_at, updated_at FROM reported_issues
|
SELECT id, user_id, user_role, subject, description, issue_type, status, metadata, created_at, updated_at
|
||||||
WHERE customer_id = $1
|
FROM reported_issues
|
||||||
|
WHERE user_id = $1
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
`
|
`
|
||||||
|
|
||||||
type ListReportedIssuesByCustomerParams struct {
|
type ListReportedIssuesByUserParams struct {
|
||||||
CustomerID int64 `json:"customer_id"`
|
UserID int64 `json:"user_id"`
|
||||||
Limit int32 `json:"limit"`
|
Limit int32 `json:"limit"`
|
||||||
Offset int32 `json:"offset"`
|
Offset int32 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListReportedIssuesByCustomerParams) ([]ReportedIssue, error) {
|
func (q *Queries) ListReportedIssuesByUser(ctx context.Context, arg ListReportedIssuesByUserParams) ([]ReportedIssue, error) {
|
||||||
rows, err := q.db.Query(ctx, ListReportedIssuesByCustomer, arg.CustomerID, arg.Limit, arg.Offset)
|
rows, err := q.db.Query(ctx, ListReportedIssuesByUser, arg.UserID, arg.Limit, arg.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +159,8 @@ func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListRepo
|
||||||
var i ReportedIssue
|
var i ReportedIssue
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.CustomerID,
|
&i.UserID,
|
||||||
|
&i.UserRole,
|
||||||
&i.Subject,
|
&i.Subject,
|
||||||
&i.Description,
|
&i.Description,
|
||||||
&i.IssueType,
|
&i.IssueType,
|
||||||
|
|
@ -166,7 +181,8 @@ func (q *Queries) ListReportedIssuesByCustomer(ctx context.Context, arg ListRepo
|
||||||
|
|
||||||
const UpdateReportedIssueStatus = `-- name: UpdateReportedIssueStatus :exec
|
const UpdateReportedIssueStatus = `-- name: UpdateReportedIssueStatus :exec
|
||||||
UPDATE reported_issues
|
UPDATE reported_issues
|
||||||
SET status = $2, updated_at = NOW()
|
SET status = $2,
|
||||||
|
updated_at = NOW()
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,9 @@ type Bet struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
UserID int64 `json:"user_id"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
|
||||||
CashedOut bool `json:"cashed_out"`
|
|
||||||
CashoutID string `json:"cashout_id"`
|
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
|
CashedOut bool `json:"cashed_out"`
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
FastCode string `json:"fast_code"`
|
FastCode string `json:"fast_code"`
|
||||||
Processed bool `json:"processed"`
|
Processed bool `json:"processed"`
|
||||||
|
|
@ -116,16 +109,9 @@ type BetWithOutcome struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
UserID int64 `json:"user_id"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
|
||||||
CashedOut bool `json:"cashed_out"`
|
|
||||||
CashoutID string `json:"cashout_id"`
|
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
|
CashedOut bool `json:"cashed_out"`
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
FastCode string `json:"fast_code"`
|
FastCode string `json:"fast_code"`
|
||||||
Processed bool `json:"processed"`
|
Processed bool `json:"processed"`
|
||||||
|
|
@ -183,26 +169,30 @@ type BranchOperation struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompaniesDetail struct {
|
type CompaniesDetail struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
AdminID int64 `json:"admin_id"`
|
AdminID int64 `json:"admin_id"`
|
||||||
WalletID int64 `json:"wallet_id"`
|
WalletID int64 `json:"wallet_id"`
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
IsActive bool `json:"is_active"`
|
||||||
Balance int64 `json:"balance"`
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
IsActive bool `json:"is_active"`
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
AdminFirstName string `json:"admin_first_name"`
|
Balance int64 `json:"balance"`
|
||||||
AdminLastName string `json:"admin_last_name"`
|
WalletIsActive bool `json:"wallet_is_active"`
|
||||||
AdminPhoneNumber pgtype.Text `json:"admin_phone_number"`
|
AdminFirstName string `json:"admin_first_name"`
|
||||||
|
AdminLastName string `json:"admin_last_name"`
|
||||||
|
AdminPhoneNumber pgtype.Text `json:"admin_phone_number"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Company struct {
|
type Company struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
AdminID int64 `json:"admin_id"`
|
AdminID int64 `json:"admin_id"`
|
||||||
WalletID int64 `json:"wallet_id"`
|
WalletID int64 `json:"wallet_id"`
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
DeductedPercentage float32 `json:"deducted_percentage"`
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
IsActive bool `json:"is_active"`
|
||||||
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CustomerWallet struct {
|
type CustomerWallet struct {
|
||||||
|
|
@ -254,6 +244,7 @@ type Event struct {
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
Source pgtype.Text `json:"source"`
|
Source pgtype.Text `json:"source"`
|
||||||
|
Flagged bool `json:"flagged"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExchangeRate struct {
|
type ExchangeRate struct {
|
||||||
|
|
@ -368,7 +359,8 @@ type RefreshToken struct {
|
||||||
|
|
||||||
type ReportedIssue struct {
|
type ReportedIssue struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
CustomerID int64 `json:"customer_id"`
|
UserID int64 `json:"user_id"`
|
||||||
|
UserRole string `json:"user_role"`
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
IssueType string `json:"issue_type"`
|
IssueType string `json:"issue_type"`
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,35 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const GetBranchWiseReport = `-- name: GetBranchWiseReport :many
|
const GetBranchWiseReport = `-- name: GetBranchWiseReport :many
|
||||||
SELECT
|
SELECT b.branch_id,
|
||||||
b.branch_id,
|
br.name AS branch_name,
|
||||||
br.name AS branch_name,
|
br.company_id,
|
||||||
br.company_id,
|
COUNT(*) AS total_bets,
|
||||||
COUNT(*) AS total_bets,
|
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
||||||
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
COALESCE(
|
||||||
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out,
|
SUM(
|
||||||
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs
|
CASE
|
||||||
FROM bets b
|
WHEN b.cashed_out THEN b.amount
|
||||||
JOIN branches br ON b.branch_id = br.id
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_out,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.status = 5 THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_backs
|
||||||
|
FROM shop_bet_detail b
|
||||||
|
JOIN branches br ON b.branch_id = br.id
|
||||||
WHERE b.created_at BETWEEN $1 AND $2
|
WHERE b.created_at BETWEEN $1 AND $2
|
||||||
GROUP BY b.branch_id, br.name, br.company_id
|
GROUP BY b.branch_id,
|
||||||
|
br.name,
|
||||||
|
br.company_id
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetBranchWiseReportParams struct {
|
type GetBranchWiseReportParams struct {
|
||||||
|
|
@ -32,7 +49,7 @@ type GetBranchWiseReportParams struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetBranchWiseReportRow struct {
|
type GetBranchWiseReportRow struct {
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
BranchID int64 `json:"branch_id"`
|
||||||
BranchName string `json:"branch_name"`
|
BranchName string `json:"branch_name"`
|
||||||
CompanyID int64 `json:"company_id"`
|
CompanyID int64 `json:"company_id"`
|
||||||
TotalBets int64 `json:"total_bets"`
|
TotalBets int64 `json:"total_bets"`
|
||||||
|
|
@ -70,17 +87,33 @@ func (q *Queries) GetBranchWiseReport(ctx context.Context, arg GetBranchWiseRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetCompanyWiseReport = `-- name: GetCompanyWiseReport :many
|
const GetCompanyWiseReport = `-- name: GetCompanyWiseReport :many
|
||||||
SELECT
|
SELECT b.company_id,
|
||||||
b.company_id,
|
c.name AS company_name,
|
||||||
c.name AS company_name,
|
COUNT(*) AS total_bets,
|
||||||
COUNT(*) AS total_bets,
|
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
||||||
COALESCE(SUM(b.amount), 0) AS total_cash_made,
|
COALESCE(
|
||||||
COALESCE(SUM(CASE WHEN b.cashed_out THEN b.amount ELSE 0 END), 0) AS total_cash_out,
|
SUM(
|
||||||
COALESCE(SUM(CASE WHEN b.status = 5 THEN b.amount ELSE 0 END), 0) AS total_cash_backs
|
CASE
|
||||||
FROM bets b
|
WHEN b.cashed_out THEN b.amount
|
||||||
JOIN companies c ON b.company_id = c.id
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_out,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN b.status = 5 THEN b.amount
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_cash_backs
|
||||||
|
FROM shop_bet_detail b
|
||||||
|
JOIN companies c ON b.company_id = c.id
|
||||||
WHERE b.created_at BETWEEN $1 AND $2
|
WHERE b.created_at BETWEEN $1 AND $2
|
||||||
GROUP BY b.company_id, c.name
|
GROUP BY b.company_id,
|
||||||
|
c.name
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetCompanyWiseReportParams struct {
|
type GetCompanyWiseReportParams struct {
|
||||||
|
|
@ -89,7 +122,7 @@ type GetCompanyWiseReportParams struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetCompanyWiseReportRow struct {
|
type GetCompanyWiseReportRow struct {
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
CompanyID int64 `json:"company_id"`
|
||||||
CompanyName string `json:"company_name"`
|
CompanyName string `json:"company_name"`
|
||||||
TotalBets int64 `json:"total_bets"`
|
TotalBets int64 `json:"total_bets"`
|
||||||
TotalCashMade interface{} `json:"total_cash_made"`
|
TotalCashMade interface{} `json:"total_cash_made"`
|
||||||
|
|
@ -123,77 +156,3 @@ func (q *Queries) GetCompanyWiseReport(ctx context.Context, arg GetCompanyWiseRe
|
||||||
}
|
}
|
||||||
return items, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -38,29 +38,23 @@ type CreateBetOutcome struct {
|
||||||
Expires time.Time `json:"expires" example:"2025-04-08T12:00:00Z"`
|
Expires time.Time `json:"expires" example:"2025-04-08T12:00:00Z"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it is a ShopBet then UserID will be the cashier
|
// If it is a ShopBet then UserID and Fullname will be the cashier
|
||||||
// If it is a DigitalBet then UserID will be the user and the branchID will be 0 or nil
|
// If it is a DigitalBet then UserID and Fullname will be the user
|
||||||
type Bet struct {
|
type Bet struct {
|
||||||
ID int64
|
ID int64
|
||||||
Amount Currency
|
Amount Currency
|
||||||
TotalOdds float32
|
TotalOdds float32
|
||||||
Status OutcomeStatus
|
Status OutcomeStatus
|
||||||
FullName string
|
UserID int64
|
||||||
PhoneNumber string
|
IsShopBet bool
|
||||||
BranchID ValidInt64 // Can Be Nullable
|
CashedOut bool
|
||||||
CompanyID ValidInt64 // Can Be Nullable
|
FastCode string
|
||||||
UserID ValidInt64 // Can Be Nullable
|
CreatedAt time.Time
|
||||||
IsShopBet bool
|
|
||||||
CashedOut bool
|
|
||||||
CashoutID string
|
|
||||||
FastCode string
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BetFilter struct {
|
type BetFilter struct {
|
||||||
BranchID ValidInt64 // Can Be Nullable
|
UserID ValidInt64
|
||||||
CompanyID ValidInt64 // Can Be Nullable
|
CashedOut ValidBool
|
||||||
UserID ValidInt64 // Can Be Nullable
|
|
||||||
IsShopBet ValidBool
|
IsShopBet ValidBool
|
||||||
Query ValidString
|
Query ValidString
|
||||||
CreatedBefore ValidTime
|
CreatedBefore ValidTime
|
||||||
|
|
@ -74,12 +68,9 @@ type GetBet struct {
|
||||||
Status OutcomeStatus
|
Status OutcomeStatus
|
||||||
FullName string
|
FullName string
|
||||||
PhoneNumber string
|
PhoneNumber string
|
||||||
BranchID ValidInt64 // Can Be Nullable
|
UserID int64
|
||||||
CompanyID ValidInt64 // Can Be Nullable
|
|
||||||
UserID ValidInt64 // Can Be Nullable
|
|
||||||
IsShopBet bool
|
IsShopBet bool
|
||||||
CashedOut bool
|
CashedOut bool
|
||||||
CashoutID string
|
|
||||||
Outcomes []BetOutcome
|
Outcomes []BetOutcome
|
||||||
FastCode string
|
FastCode string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
|
|
@ -89,13 +80,8 @@ type CreateBet struct {
|
||||||
Amount Currency
|
Amount Currency
|
||||||
TotalOdds float32
|
TotalOdds float32
|
||||||
Status OutcomeStatus
|
Status OutcomeStatus
|
||||||
FullName string
|
UserID int64
|
||||||
PhoneNumber string
|
|
||||||
CompanyID ValidInt64 // Can Be Nullable
|
|
||||||
BranchID ValidInt64 // Can Be Nullable
|
|
||||||
UserID ValidInt64 // Can Be Nullable
|
|
||||||
IsShopBet bool
|
IsShopBet bool
|
||||||
CashoutID string
|
|
||||||
OutcomesHash string
|
OutcomesHash string
|
||||||
FastCode string
|
FastCode string
|
||||||
}
|
}
|
||||||
|
|
@ -109,8 +95,6 @@ type CreateBetOutcomeReq struct {
|
||||||
type CreateBetReq struct {
|
type CreateBetReq struct {
|
||||||
Outcomes []CreateBetOutcomeReq `json:"outcomes" validate:"required"`
|
Outcomes []CreateBetOutcomeReq `json:"outcomes" validate:"required"`
|
||||||
Amount float32 `json:"amount" validate:"required,gt=0" example:"100.0"`
|
Amount float32 `json:"amount" validate:"required,gt=0" example:"100.0"`
|
||||||
FullName string `json:"full_name" example:"John"`
|
|
||||||
PhoneNumber string `json:"phone_number" validate:"required" example:"1234567890"`
|
|
||||||
BranchID *int64 `json:"branch_id,omitempty" validate:"required" example:"1"`
|
BranchID *int64 `json:"branch_id,omitempty" validate:"required" example:"1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,28 +108,22 @@ type CreateBetRes struct {
|
||||||
Amount float32 `json:"amount" example:"100.0"`
|
Amount float32 `json:"amount" example:"100.0"`
|
||||||
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
||||||
Status OutcomeStatus `json:"status" example:"1"`
|
Status OutcomeStatus `json:"status" example:"1"`
|
||||||
FullName string `json:"full_name" example:"John"`
|
|
||||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
|
||||||
BranchID int64 `json:"branch_id" example:"2"`
|
|
||||||
UserID int64 `json:"user_id" example:"2"`
|
UserID int64 `json:"user_id" example:"2"`
|
||||||
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
||||||
CreatedNumber int64 `json:"created_number" example:"2"`
|
CreatedNumber int64 `json:"created_number" example:"2"`
|
||||||
CashedID string `json:"cashed_id" example:"21234"`
|
|
||||||
}
|
}
|
||||||
type BetRes struct {
|
type BetRes struct {
|
||||||
ID int64 `json:"id" example:"1"`
|
ID int64 `json:"id" example:"1"`
|
||||||
Outcomes []BetOutcome `json:"outcomes"`
|
Outcomes []BetOutcome `json:"outcomes"`
|
||||||
Amount float32 `json:"amount" example:"100.0"`
|
Amount float32 `json:"amount" example:"100.0"`
|
||||||
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
||||||
Status OutcomeStatus `json:"status" example:"1"`
|
Status OutcomeStatus `json:"status" example:"1"`
|
||||||
FullName string `json:"full_name" example:"John"`
|
Fullname string `json:"full_name" example:"John Smith"`
|
||||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
UserID int64 `json:"user_id" example:"2"`
|
||||||
BranchID int64 `json:"branch_id" example:"2"`
|
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
||||||
UserID int64 `json:"user_id" example:"2"`
|
CashedOut bool `json:"cashed_out" example:"false"`
|
||||||
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"`
|
||||||
CashedOut bool `json:"cashed_out" example:"false"`
|
FastCode string `json:"fast_code"`
|
||||||
CashedID string `json:"cashed_id" example:"21234"`
|
|
||||||
CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes {
|
func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes {
|
||||||
|
|
@ -154,29 +132,23 @@ func ConvertCreateBet(bet Bet, createdNumber int64) CreateBetRes {
|
||||||
Amount: bet.Amount.Float32(),
|
Amount: bet.Amount.Float32(),
|
||||||
TotalOdds: bet.TotalOdds,
|
TotalOdds: bet.TotalOdds,
|
||||||
Status: bet.Status,
|
Status: bet.Status,
|
||||||
FullName: bet.FullName,
|
UserID: bet.UserID,
|
||||||
PhoneNumber: bet.PhoneNumber,
|
|
||||||
BranchID: bet.BranchID.Value,
|
|
||||||
UserID: bet.UserID.Value,
|
|
||||||
CreatedNumber: createdNumber,
|
CreatedNumber: createdNumber,
|
||||||
CashedID: bet.CashoutID,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertBet(bet GetBet) BetRes {
|
func ConvertBet(bet GetBet) BetRes {
|
||||||
return BetRes{
|
return BetRes{
|
||||||
ID: bet.ID,
|
ID: bet.ID,
|
||||||
Amount: bet.Amount.Float32(),
|
Amount: bet.Amount.Float32(),
|
||||||
TotalOdds: bet.TotalOdds,
|
TotalOdds: bet.TotalOdds,
|
||||||
Status: bet.Status,
|
Status: bet.Status,
|
||||||
FullName: bet.FullName,
|
Fullname: bet.FullName,
|
||||||
PhoneNumber: bet.PhoneNumber,
|
UserID: bet.UserID,
|
||||||
BranchID: bet.BranchID.Value,
|
Outcomes: bet.Outcomes,
|
||||||
UserID: bet.UserID.Value,
|
IsShopBet: bet.IsShopBet,
|
||||||
Outcomes: bet.Outcomes,
|
CashedOut: bet.CashedOut,
|
||||||
IsShopBet: bet.IsShopBet,
|
CreatedAt: bet.CreatedAt,
|
||||||
CashedOut: bet.CashedOut,
|
FastCode: bet.FastCode,
|
||||||
CashedID: bet.CashoutID,
|
|
||||||
CreatedAt: bet.CreatedAt,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,3 +74,98 @@ type CreateBranchOperation struct {
|
||||||
BranchID int64
|
BranchID int64
|
||||||
OperationID 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
|
Valid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ValidFloat32 struct {
|
||||||
|
Value float32
|
||||||
|
Valid bool
|
||||||
|
}
|
||||||
|
|
||||||
type ValidString struct {
|
type ValidString struct {
|
||||||
Value string
|
Value string
|
||||||
Valid bool
|
Valid bool
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,226 @@
|
||||||
package domain
|
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
|
// Company represents the client that we will contract the services with
|
||||||
// they are the ones that manage the branches and branch managers
|
// 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
|
// they will have their own wallet that they will use to distribute to the branch wallets
|
||||||
type Company struct {
|
type Company struct {
|
||||||
ID int64
|
ID int64
|
||||||
Name string
|
Name string
|
||||||
AdminID int64
|
AdminID int64
|
||||||
WalletID int64
|
WalletID int64
|
||||||
|
DeductedPercentage float32
|
||||||
|
IsActive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompanyFilter struct {
|
type CompanyFilter struct {
|
||||||
IsActive ValidBool
|
IsActive ValidBool
|
||||||
Query ValidString
|
Query ValidString
|
||||||
CreatedBefore ValidTime
|
CreatedBefore ValidTime
|
||||||
CreatedAfter ValidTime
|
CreatedAfter ValidTime
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetCompany struct {
|
type GetCompany struct {
|
||||||
ID int64
|
ID int64
|
||||||
Name string
|
Name string
|
||||||
AdminID int64
|
AdminID int64
|
||||||
AdminFirstName string
|
AdminFirstName string
|
||||||
AdminLastName string
|
AdminLastName string
|
||||||
AdminPhoneNumber string
|
AdminPhoneNumber string
|
||||||
WalletID int64
|
WalletID int64
|
||||||
WalletBalance Currency
|
WalletBalance Currency
|
||||||
IsWalletActive bool
|
IsWalletActive bool
|
||||||
|
DeductedPercentage float32
|
||||||
|
IsActive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateCompany struct {
|
type CreateCompany struct {
|
||||||
Name string
|
Name string
|
||||||
AdminID int64
|
AdminID int64
|
||||||
WalletID int64
|
WalletID int64
|
||||||
|
DeductedPercentage float32
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateCompany struct {
|
type UpdateCompany struct {
|
||||||
ID int64
|
ID int64
|
||||||
Name *string
|
Name ValidString
|
||||||
AdminID *int64
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ type UpcomingEvent struct {
|
||||||
StartTime time.Time `json:"start_time"` // Converted from "time" field in UNIX format
|
StartTime time.Time `json:"start_time"` // Converted from "time" field in UNIX format
|
||||||
Source string `json:"source"` // bet api provider (bet365, betfair)
|
Source string `json:"source"` // bet api provider (bet365, betfair)
|
||||||
Status EventStatus `json:"status"` //Match Status for event
|
Status EventStatus `json:"status"` //Match Status for event
|
||||||
|
Flagged bool `json:"flagged"` //Whether the event is flagged or not
|
||||||
}
|
}
|
||||||
type MatchResult struct {
|
type MatchResult struct {
|
||||||
EventID string
|
EventID string
|
||||||
|
|
@ -127,4 +128,5 @@ type EventFilter struct {
|
||||||
Limit ValidInt64
|
Limit ValidInt64
|
||||||
Offset ValidInt64
|
Offset ValidInt64
|
||||||
MatchStatus ValidString // e.g., "upcoming", "in_play", "ended"
|
MatchStatus ValidString // e.g., "upcoming", "in_play", "ended"
|
||||||
|
Flagged ValidBool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,51 @@ package domain
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
type ReportedIssueType string
|
||||||
|
|
||||||
|
var (
|
||||||
|
ISSUE_TYPE_DEPOSIT ReportedIssueType = "deposit"
|
||||||
|
ISSUE_TYPE_WITHDRAWAL ReportedIssueType = "withdrawal"
|
||||||
|
ISSUE_TYPE_BET ReportedIssueType = "bet"
|
||||||
|
ISSUE_TYPE_CASHOUT ReportedIssueType = "cashout"
|
||||||
|
ISSUE_TYPE_ODDS ReportedIssueType = "odds"
|
||||||
|
ISSUE_TYPE_EVENTS ReportedIssueType = "events"
|
||||||
|
ISSUE_TYPE_BRANCH ReportedIssueType = "branch"
|
||||||
|
ISSUE_TYPE_USER ReportedIssueType = "branch"
|
||||||
|
ISSUE_TYPE_LOGIN ReportedIssueType = "login"
|
||||||
|
ISSUE_TYPE_REGISTER ReportedIssueType = "register"
|
||||||
|
ISSUE_TYPE_RESET_PASSWORD ReportedIssueType = "reset_password"
|
||||||
|
ISSUE_TYPE_WALLET ReportedIssueType = "wallet"
|
||||||
|
ISSUE_TYPE_VIRTUAL ReportedIssueType = "virtual games"
|
||||||
|
ISSUE_TYPE_OTHER ReportedIssueType = "other"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReportedIssueStatus string
|
||||||
|
|
||||||
|
var (
|
||||||
|
ISSUE_STATUS_PENDING ReportedIssueStatus = "pending"
|
||||||
|
ISSUE_STATUS_IN_PROGRESS ReportedIssueStatus = "in_progress"
|
||||||
|
ISSUE_STATUS_RESOLVED ReportedIssueStatus = "resolved"
|
||||||
|
ISSUE_STATUS_REJECTED ReportedIssueStatus = "rejected"
|
||||||
|
)
|
||||||
|
|
||||||
type ReportedIssue struct {
|
type ReportedIssue struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
CustomerID int64 `json:"customer_id"`
|
UserID int64 `json:"user_id"`
|
||||||
|
UserRole Role `json:"user_role"`
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
IssueType string `json:"issue_type"`
|
IssueType ReportedIssueType `json:"issue_type"`
|
||||||
Status string `json:"status"`
|
Status ReportedIssueStatus `json:"status"`
|
||||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReportedIssueReq struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Subject string `json:"subject"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
IssueType ReportedIssueType `json:"issue_type"`
|
||||||
|
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package domain
|
package domain
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Setting struct {
|
type Setting struct {
|
||||||
Key string
|
Key string
|
||||||
|
|
@ -15,8 +17,37 @@ type SettingRes struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SettingList struct {
|
type SettingList struct {
|
||||||
MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"`
|
MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"`
|
||||||
BetAmountLimit Currency `json:"bet_amount_limit"`
|
BetAmountLimit Currency `json:"bet_amount_limit"`
|
||||||
DailyTicketPerIP int64 `json:"daily_ticket_limit"`
|
DailyTicketPerIP int64 `json:"daily_ticket_limit"`
|
||||||
TotalWinningLimit Currency `json:"total_winning_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
|
return newTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateTransactionVerifiedReq struct {
|
||||||
|
Verified bool `json:"verified" example:"true"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,27 +21,14 @@ var (
|
||||||
|
|
||||||
func convertDBBet(bet dbgen.Bet) domain.Bet {
|
func convertDBBet(bet dbgen.Bet) domain.Bet {
|
||||||
return domain.Bet{
|
return domain.Bet{
|
||||||
ID: bet.ID,
|
ID: bet.ID,
|
||||||
Amount: domain.Currency(bet.Amount),
|
Amount: domain.Currency(bet.Amount),
|
||||||
TotalOdds: bet.TotalOdds,
|
TotalOdds: bet.TotalOdds,
|
||||||
Status: domain.OutcomeStatus(bet.Status),
|
Status: domain.OutcomeStatus(bet.Status),
|
||||||
FullName: bet.FullName,
|
UserID: bet.UserID,
|
||||||
PhoneNumber: bet.PhoneNumber,
|
|
||||||
BranchID: domain.ValidInt64{
|
|
||||||
Value: bet.BranchID.Int64,
|
|
||||||
Valid: bet.BranchID.Valid,
|
|
||||||
},
|
|
||||||
CompanyID: domain.ValidInt64{
|
|
||||||
Value: bet.CompanyID.Int64,
|
|
||||||
Valid: bet.CompanyID.Valid,
|
|
||||||
},
|
|
||||||
UserID: domain.ValidInt64{
|
|
||||||
Value: bet.UserID.Int64,
|
|
||||||
Valid: bet.UserID.Valid,
|
|
||||||
},
|
|
||||||
IsShopBet: bet.IsShopBet,
|
IsShopBet: bet.IsShopBet,
|
||||||
CashedOut: bet.CashedOut,
|
CashedOut: bet.CashedOut,
|
||||||
CashoutID: bet.CashoutID,
|
FastCode: bet.FastCode,
|
||||||
CreatedAt: bet.CreatedAt.Time,
|
CreatedAt: bet.CreatedAt.Time,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -78,21 +65,14 @@ func convertDBBetWithOutcomes(bet dbgen.BetWithOutcome) domain.GetBet {
|
||||||
Amount: domain.Currency(bet.Amount),
|
Amount: domain.Currency(bet.Amount),
|
||||||
TotalOdds: bet.TotalOdds,
|
TotalOdds: bet.TotalOdds,
|
||||||
Status: domain.OutcomeStatus(bet.Status),
|
Status: domain.OutcomeStatus(bet.Status),
|
||||||
FullName: bet.FullName,
|
FullName: bet.FullName.(string),
|
||||||
PhoneNumber: bet.PhoneNumber,
|
PhoneNumber: bet.PhoneNumber.String,
|
||||||
BranchID: domain.ValidInt64{
|
UserID: bet.UserID,
|
||||||
Value: bet.BranchID.Int64,
|
IsShopBet: bet.IsShopBet,
|
||||||
Valid: bet.BranchID.Valid,
|
CashedOut: bet.CashedOut,
|
||||||
},
|
Outcomes: outcomes,
|
||||||
UserID: domain.ValidInt64{
|
FastCode: bet.FastCode,
|
||||||
Value: bet.UserID.Int64,
|
CreatedAt: bet.CreatedAt.Time,
|
||||||
Valid: bet.UserID.Valid,
|
|
||||||
},
|
|
||||||
IsShopBet: bet.IsShopBet,
|
|
||||||
CashedOut: bet.CashedOut,
|
|
||||||
CashoutID: bet.CashoutID,
|
|
||||||
Outcomes: outcomes,
|
|
||||||
CreatedAt: bet.CreatedAt.Time,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,22 +99,11 @@ func convertDBCreateBetOutcome(betOutcome domain.CreateBetOutcome) dbgen.CreateB
|
||||||
|
|
||||||
func convertCreateBet(bet domain.CreateBet) dbgen.CreateBetParams {
|
func convertCreateBet(bet domain.CreateBet) dbgen.CreateBetParams {
|
||||||
return dbgen.CreateBetParams{
|
return dbgen.CreateBetParams{
|
||||||
Amount: int64(bet.Amount),
|
Amount: int64(bet.Amount),
|
||||||
TotalOdds: bet.TotalOdds,
|
TotalOdds: bet.TotalOdds,
|
||||||
Status: int32(bet.Status),
|
Status: int32(bet.Status),
|
||||||
FullName: bet.FullName,
|
UserID: bet.UserID,
|
||||||
PhoneNumber: bet.PhoneNumber,
|
|
||||||
|
|
||||||
BranchID: pgtype.Int8{
|
|
||||||
Int64: bet.BranchID.Value,
|
|
||||||
Valid: bet.BranchID.Valid,
|
|
||||||
},
|
|
||||||
UserID: pgtype.Int8{
|
|
||||||
Int64: bet.UserID.Value,
|
|
||||||
Valid: bet.UserID.Valid,
|
|
||||||
},
|
|
||||||
IsShopBet: bet.IsShopBet,
|
IsShopBet: bet.IsShopBet,
|
||||||
CashoutID: bet.CashoutID,
|
|
||||||
OutcomesHash: bet.OutcomesHash,
|
OutcomesHash: bet.OutcomesHash,
|
||||||
FastCode: bet.FastCode,
|
FastCode: bet.FastCode,
|
||||||
}
|
}
|
||||||
|
|
@ -184,33 +153,16 @@ func (s *Store) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
|
||||||
return convertDBBetWithOutcomes(bet), nil
|
return convertDBBetWithOutcomes(bet), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error) {
|
|
||||||
bet, err := s.queries.GetBetByCashoutID(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
domain.MongoDBLogger.Error("failed to get bet by cashout ID",
|
|
||||||
zap.String("cashout_id", id),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return domain.GetBet{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertDBBetWithOutcomes(bet), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
|
func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
|
||||||
bets, err := s.queries.GetAllBets(ctx, dbgen.GetAllBetsParams{
|
bets, err := s.queries.GetAllBets(ctx, dbgen.GetAllBetsParams{
|
||||||
BranchID: pgtype.Int8{
|
|
||||||
Int64: filter.BranchID.Value,
|
|
||||||
Valid: filter.BranchID.Valid,
|
|
||||||
},
|
|
||||||
CompanyID: pgtype.Int8{
|
|
||||||
Int64: filter.CompanyID.Value,
|
|
||||||
Valid: filter.CompanyID.Valid,
|
|
||||||
},
|
|
||||||
UserID: pgtype.Int8{
|
UserID: pgtype.Int8{
|
||||||
Int64: filter.UserID.Value,
|
Int64: filter.UserID.Value,
|
||||||
Valid: filter.UserID.Valid,
|
Valid: filter.UserID.Valid,
|
||||||
},
|
},
|
||||||
|
CashedOut: pgtype.Bool{
|
||||||
|
Bool: filter.CashedOut.Value,
|
||||||
|
Valid: filter.CashedOut.Valid,
|
||||||
|
},
|
||||||
IsShopBet: pgtype.Bool{
|
IsShopBet: pgtype.Bool{
|
||||||
Bool: filter.IsShopBet.Value,
|
Bool: filter.IsShopBet.Value,
|
||||||
Valid: filter.IsShopBet.Valid,
|
Valid: filter.IsShopBet.Valid,
|
||||||
|
|
@ -244,32 +196,8 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetBetByBranchID(ctx context.Context, BranchID int64) ([]domain.GetBet, error) {
|
|
||||||
bets, err := s.queries.GetBetByBranchID(ctx, pgtype.Int8{
|
|
||||||
Int64: BranchID,
|
|
||||||
Valid: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
domain.MongoDBLogger.Error("failed to get bets by branch ID",
|
|
||||||
zap.Int64("branch_id", BranchID),
|
|
||||||
zap.Error(err),
|
|
||||||
)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []domain.GetBet = make([]domain.GetBet, 0, len(bets))
|
|
||||||
for _, bet := range bets {
|
|
||||||
result = append(result, convertDBBetWithOutcomes(bet))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Store) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) {
|
func (s *Store) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) {
|
||||||
bets, err := s.queries.GetBetByUserID(ctx, pgtype.Int8{
|
bets, err := s.queries.GetBetByUserID(ctx, UserID)
|
||||||
Int64: UserID,
|
|
||||||
Valid: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -311,7 +239,7 @@ func (s *Store) GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error)
|
||||||
|
|
||||||
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||||
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
||||||
UserID: pgtype.Int8{Int64: UserID, Valid: true},
|
UserID: UserID,
|
||||||
OutcomesHash: outcomesHash,
|
OutcomesHash: outcomesHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -496,23 +424,23 @@ func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
// query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
// query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
// if len(args) == 0 {
|
||||||
return " WHERE "
|
// return " WHERE "
|
||||||
}
|
// }
|
||||||
return " AND "
|
// return " AND "
|
||||||
}(), argPos)
|
// }(), argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
query += fmt.Sprintf(" %suser_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return " WHERE "
|
return " WHERE "
|
||||||
}
|
}
|
||||||
|
|
@ -586,21 +514,21 @@ func (s *Store) GetBetStats(ctx context.Context, filter domain.ReportFilter) ([]
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
// query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
// query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
// if len(args) == 0 {
|
||||||
return " WHERE "
|
// return " WHERE "
|
||||||
}
|
// }
|
||||||
return " AND "
|
// return " AND "
|
||||||
}(), argPos)
|
// }(), argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
@ -700,16 +628,16 @@ func (s *Store) GetSportPopularity(ctx context.Context, filter domain.ReportFilt
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
@ -790,16 +718,6 @@ func (s *Store) GetMarketPopularity(ctx context.Context, filter domain.ReportFil
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// 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 {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
@ -876,21 +794,21 @@ func (s *Store) GetExtremeValues(ctx context.Context, filter domain.ReportFilter
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
// query += fmt.Sprintf(" WHERE company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
// query += fmt.Sprintf(" AND %sbranch_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
// if len(args) == 0 {
|
||||||
return " WHERE "
|
// return " WHERE "
|
||||||
}
|
// }
|
||||||
return " AND "
|
// return " AND "
|
||||||
}(), argPos)
|
// }(), argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
query += fmt.Sprintf(" AND %suser_id = $%d", func() string {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
@ -986,16 +904,16 @@ func (s *Store) GetCustomerBetActivity(ctx context.Context, filter domain.Report
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
@ -1081,16 +999,16 @@ func (s *Store) GetBranchBetActivity(ctx context.Context, filter domain.ReportFi
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
// Add filters if provided
|
// Add filters if provided
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.StartTime.Valid {
|
if filter.StartTime.Valid {
|
||||||
query += fmt.Sprintf(" AND created_at >= $%d", argPos)
|
query += fmt.Sprintf(" AND created_at >= $%d", argPos)
|
||||||
args = append(args, filter.StartTime.Value)
|
args = append(args, filter.StartTime.Value)
|
||||||
|
|
@ -1165,16 +1083,16 @@ func (s *Store) GetSportBetActivity(ctx context.Context, filter domain.ReportFil
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
@ -1250,16 +1168,16 @@ func (s *Store) GetSportDetails(ctx context.Context, filter domain.ReportFilter)
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
@ -1326,16 +1244,16 @@ func (s *Store) GetSportMarketPopularity(ctx context.Context, filter domain.Repo
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
argPos := 1
|
argPos := 1
|
||||||
|
|
||||||
if filter.CompanyID.Valid {
|
// if filter.CompanyID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.company_id = $%d", argPos)
|
||||||
args = append(args, filter.CompanyID.Value)
|
// args = append(args, filter.CompanyID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.BranchID.Valid {
|
// if filter.BranchID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
// query += fmt.Sprintf(" AND b.branch_id = $%d", argPos)
|
||||||
args = append(args, filter.BranchID.Value)
|
// args = append(args, filter.BranchID.Value)
|
||||||
argPos++
|
// argPos++
|
||||||
}
|
// }
|
||||||
if filter.UserID.Valid {
|
if filter.UserID.Valid {
|
||||||
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
query += fmt.Sprintf(" AND b.user_id = $%d", argPos)
|
||||||
args = append(args, filter.UserID.Value)
|
args = append(args, filter.UserID.Value)
|
||||||
|
|
|
||||||
|
|
@ -3,95 +3,28 @@ package repository
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"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) {
|
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 {
|
if err != nil {
|
||||||
return domain.Company{}, err
|
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) {
|
func (s *Store) GetAllCompanies(ctx context.Context, filter domain.CompanyFilter) ([]domain.GetCompany, error) {
|
||||||
dbCompanies, err := s.queries.GetAllCompanies(ctx, dbgen.GetAllCompaniesParams{
|
dbCompanies, err := s.queries.GetAllCompanies(ctx, domain.ConvertGetAllCompaniesParams(filter))
|
||||||
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,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var companies []domain.GetCompany = make([]domain.GetCompany, 0, len(dbCompanies))
|
var companies []domain.GetCompany = make([]domain.GetCompany, 0, len(dbCompanies))
|
||||||
for _, dbCompany := range dbCompanies {
|
for _, dbCompany := range dbCompanies {
|
||||||
companies = append(companies, convertDBCompanyDetails(dbCompany))
|
companies = append(companies, domain.ConvertDBCompanyDetails(dbCompany))
|
||||||
}
|
}
|
||||||
|
|
||||||
return companies, nil
|
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))
|
var companies []domain.GetCompany = make([]domain.GetCompany, 0, len(dbCompanies))
|
||||||
|
|
||||||
for _, dbCompany := range dbCompanies {
|
for _, dbCompany := range dbCompanies {
|
||||||
companies = append(companies, convertDBCompanyDetails(dbCompany))
|
companies = append(companies, domain.ConvertDBCompanyDetails(dbCompany))
|
||||||
}
|
}
|
||||||
return companies, nil
|
return companies, nil
|
||||||
}
|
}
|
||||||
|
|
@ -120,17 +53,17 @@ func (s *Store) GetCompanyByID(ctx context.Context, id int64) (domain.GetCompany
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.GetCompany{}, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return domain.Company{}, err
|
return domain.Company{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertDBCompany(dbCompany), nil
|
return domain.ConvertDBCompany(dbCompany), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteCompany(ctx context.Context, id int64) error {
|
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(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
Source: e.Source.String,
|
Source: e.Source.String,
|
||||||
Status: domain.EventStatus(e.Status.String),
|
Status: domain.EventStatus(e.Status.String),
|
||||||
|
Flagged: e.Flagged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return upcomingEvents, nil
|
return upcomingEvents, nil
|
||||||
|
|
@ -121,6 +122,7 @@ func (s *Store) GetExpiredUpcomingEvents(ctx context.Context, filter domain.Even
|
||||||
StartTime: e.StartTime.Time.UTC(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
Source: e.Source.String,
|
Source: e.Source.String,
|
||||||
Status: domain.EventStatus(e.Status.String),
|
Status: domain.EventStatus(e.Status.String),
|
||||||
|
Flagged: e.Flagged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return upcomingEvents, nil
|
return upcomingEvents, nil
|
||||||
|
|
@ -157,6 +159,10 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
||||||
String: filter.CountryCode.Value,
|
String: filter.CountryCode.Value,
|
||||||
Valid: filter.CountryCode.Valid,
|
Valid: filter.CountryCode.Valid,
|
||||||
},
|
},
|
||||||
|
Flagged: pgtype.Bool{
|
||||||
|
Bool: filter.Flagged.Valid,
|
||||||
|
Valid: filter.Flagged.Valid,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -180,6 +186,7 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
||||||
StartTime: e.StartTime.Time.UTC(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
Source: e.Source.String,
|
Source: e.Source.String,
|
||||||
Status: domain.EventStatus(e.Status.String),
|
Status: domain.EventStatus(e.Status.String),
|
||||||
|
Flagged: e.Flagged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
|
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
|
||||||
|
|
@ -203,6 +210,10 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, filter domain.Ev
|
||||||
String: filter.CountryCode.Value,
|
String: filter.CountryCode.Value,
|
||||||
Valid: filter.CountryCode.Valid,
|
Valid: filter.CountryCode.Valid,
|
||||||
},
|
},
|
||||||
|
Flagged: pgtype.Bool{
|
||||||
|
Bool: filter.Flagged.Valid,
|
||||||
|
Valid: filter.Flagged.Valid,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
|
@ -233,6 +244,7 @@ func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.Upc
|
||||||
StartTime: event.StartTime.Time.UTC(),
|
StartTime: event.StartTime.Time.UTC(),
|
||||||
Source: event.Source.String,
|
Source: event.Source.String,
|
||||||
Status: domain.EventStatus(event.Status.String),
|
Status: domain.EventStatus(event.Status.String),
|
||||||
|
Flagged: event.Flagged,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
|
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error {
|
||||||
|
|
@ -268,6 +280,13 @@ func (s *Store) UpdateEventStatus(ctx context.Context, eventID string, status do
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) UpdateFlagged(ctx context.Context, eventID string, flagged bool) error {
|
||||||
|
return s.queries.UpdateFlagged(ctx, dbgen.UpdateFlaggedParams{
|
||||||
|
ID: eventID,
|
||||||
|
Flagged: flagged,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteEvent(ctx context.Context, eventID string) error {
|
func (s *Store) DeleteEvent(ctx context.Context, eventID string) error {
|
||||||
err := s.queries.DeleteEvent(ctx, eventID)
|
err := s.queries.DeleteEvent(ctx, eventID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import (
|
||||||
type ReportedIssueRepository interface {
|
type ReportedIssueRepository interface {
|
||||||
CreateReportedIssue(ctx context.Context, arg dbgen.CreateReportedIssueParams) (dbgen.ReportedIssue, error)
|
CreateReportedIssue(ctx context.Context, arg dbgen.CreateReportedIssueParams) (dbgen.ReportedIssue, error)
|
||||||
ListReportedIssues(ctx context.Context, limit, offset int32) ([]dbgen.ReportedIssue, error)
|
ListReportedIssues(ctx context.Context, limit, offset int32) ([]dbgen.ReportedIssue, error)
|
||||||
ListReportedIssuesByCustomer(ctx context.Context, customerID int64, limit, offset int32) ([]dbgen.ReportedIssue, error)
|
ListReportedIssuesByUser(ctx context.Context, userID int64, limit, offset int32) ([]dbgen.ReportedIssue, error)
|
||||||
CountReportedIssues(ctx context.Context) (int64, error)
|
CountReportedIssues(ctx context.Context) (int64, error)
|
||||||
CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error)
|
CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error)
|
||||||
UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error
|
UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error
|
||||||
DeleteReportedIssue(ctx context.Context, id int64) error
|
DeleteReportedIssue(ctx context.Context, id int64) error
|
||||||
}
|
}
|
||||||
|
|
@ -36,21 +36,21 @@ func (s *ReportedIssueRepo) ListReportedIssues(ctx context.Context, limit, offse
|
||||||
return s.store.queries.ListReportedIssues(ctx, params)
|
return s.store.queries.ListReportedIssues(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ReportedIssueRepo) ListReportedIssuesByCustomer(ctx context.Context, customerID int64, limit, offset int32) ([]dbgen.ReportedIssue, error) {
|
func (s *ReportedIssueRepo) ListReportedIssuesByUser(ctx context.Context, userID int64, limit, offset int32) ([]dbgen.ReportedIssue, error) {
|
||||||
params := dbgen.ListReportedIssuesByCustomerParams{
|
params := dbgen.ListReportedIssuesByUserParams{
|
||||||
CustomerID: customerID,
|
UserID: userID,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
return s.store.queries.ListReportedIssuesByCustomer(ctx, params)
|
return s.store.queries.ListReportedIssuesByUser(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ReportedIssueRepo) CountReportedIssues(ctx context.Context) (int64, error) {
|
func (s *ReportedIssueRepo) CountReportedIssues(ctx context.Context) (int64, error) {
|
||||||
return s.store.queries.CountReportedIssues(ctx)
|
return s.store.queries.CountReportedIssues(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ReportedIssueRepo) CountReportedIssuesByCustomer(ctx context.Context, customerID int64) (int64, error) {
|
func (s *ReportedIssueRepo) CountReportedIssuesByUser(ctx context.Context, userID int64) (int64, error) {
|
||||||
return s.store.queries.CountReportedIssuesByCustomer(ctx, customerID)
|
return s.store.queries.CountReportedIssuesByUser(ctx, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ReportedIssueRepo) UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error {
|
func (s *ReportedIssueRepo) UpdateReportedIssueStatus(ctx context.Context, id int64, status string) error {
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,16 @@ import (
|
||||||
"go.uber.org/zap"
|
"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) {
|
func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
var dbSettingList DBSettingList
|
var dbSettingList domain.DBSettingList
|
||||||
var int64SettingsMap = map[string]*domain.ValidInt64{
|
// var int64SettingsMap = map[string]*domain.ValidInt64{
|
||||||
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
// "max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||||
"bet_amount_limit": &dbSettingList.BetAmountLimit,
|
// "bet_amount_limit": &dbSettingList.BetAmountLimit,
|
||||||
"daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
// "daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
||||||
"total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
// "total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
var int64SettingsMap = domain.ConvertInt64SettingsMap(&dbSettingList)
|
||||||
|
|
||||||
for _, setting := range settings {
|
for _, setting := range settings {
|
||||||
is_setting_unknown := true
|
is_setting_unknown := true
|
||||||
|
|
@ -54,12 +49,7 @@ func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.SettingList{
|
return domain.ConvertDBSetting(dbSettingList), nil
|
||||||
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
|
||||||
BetAmountLimit: domain.Currency(dbSettingList.BetAmountLimit.Value),
|
|
||||||
DailyTicketPerIP: dbSettingList.DailyTicketPerIP.Value,
|
|
||||||
TotalWinningLimit: domain.Currency(dbSettingList.TotalWinningLimit.Value),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
||||||
settings, err := s.queries.GetSettings(ctx)
|
settings, err := s.queries.GetSettings(ctx)
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,8 @@ import (
|
||||||
type BetStore interface {
|
type BetStore interface {
|
||||||
CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error)
|
CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error)
|
||||||
CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBetOutcome) (int64, 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)
|
GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
|
||||||
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]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)
|
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
|
||||||
GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, error)
|
GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, error)
|
||||||
GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
|
GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,11 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||||
|
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
@ -37,16 +40,23 @@ var (
|
||||||
ErrBranchIDRequired = errors.New("Branch ID required for this role")
|
ErrBranchIDRequired = errors.New("Branch ID required for this role")
|
||||||
ErrOutcomeLimit = errors.New("Too many outcomes on a single bet")
|
ErrOutcomeLimit = errors.New("Too many outcomes on a single bet")
|
||||||
ErrTotalBalanceNotEnough = errors.New("Total Wallet balance is insufficient to create bet")
|
ErrTotalBalanceNotEnough = errors.New("Total Wallet balance is insufficient to create bet")
|
||||||
|
|
||||||
|
ErrInvalidAmount = errors.New("Invalid amount")
|
||||||
|
ErrBetAmountTooHigh = errors.New("Cannot create a bet with an amount above limit")
|
||||||
|
ErrBetWinningTooHigh = errors.New("Total Winnings over set limit")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
betStore BetStore
|
betStore BetStore
|
||||||
eventSvc event.Service
|
eventSvc event.Service
|
||||||
prematchSvc odds.ServiceImpl
|
prematchSvc odds.ServiceImpl
|
||||||
walletSvc wallet.Service
|
walletSvc wallet.Service
|
||||||
branchSvc branch.Service
|
branchSvc branch.Service
|
||||||
logger *slog.Logger
|
companySvc company.Service
|
||||||
mongoLogger *zap.Logger
|
settingSvc settings.Service
|
||||||
|
notificationSvc *notificationservice.Service
|
||||||
|
logger *slog.Logger
|
||||||
|
mongoLogger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(
|
func NewService(
|
||||||
|
|
@ -55,17 +65,23 @@ func NewService(
|
||||||
prematchSvc odds.ServiceImpl,
|
prematchSvc odds.ServiceImpl,
|
||||||
walletSvc wallet.Service,
|
walletSvc wallet.Service,
|
||||||
branchSvc branch.Service,
|
branchSvc branch.Service,
|
||||||
|
companySvc company.Service,
|
||||||
|
settingSvc settings.Service,
|
||||||
|
notificationSvc *notificationservice.Service,
|
||||||
logger *slog.Logger,
|
logger *slog.Logger,
|
||||||
mongoLogger *zap.Logger,
|
mongoLogger *zap.Logger,
|
||||||
) *Service {
|
) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
betStore: betStore,
|
betStore: betStore,
|
||||||
eventSvc: eventSvc,
|
eventSvc: eventSvc,
|
||||||
prematchSvc: prematchSvc,
|
prematchSvc: prematchSvc,
|
||||||
walletSvc: walletSvc,
|
walletSvc: walletSvc,
|
||||||
branchSvc: branchSvc,
|
branchSvc: branchSvc,
|
||||||
logger: logger,
|
companySvc: companySvc,
|
||||||
mongoLogger: mongoLogger,
|
settingSvc: settingSvc,
|
||||||
|
notificationSvc: notificationSvc,
|
||||||
|
logger: logger,
|
||||||
|
mongoLogger: mongoLogger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -196,9 +212,19 @@ func (s *Service) GenerateBetOutcome(ctx context.Context, eventID int64, marketI
|
||||||
return newOutcome, nil
|
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) {
|
||||||
if len(req.Outcomes) > 30 {
|
settingsList, err := s.settingSvc.GetSettingList(ctx)
|
||||||
s.mongoLogger.Error("too many outcomes",
|
|
||||||
|
if req.Amount < 1 {
|
||||||
|
return domain.CreateBetRes{}, ErrInvalidAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Amount > settingsList.BetAmountLimit.Float32() {
|
||||||
|
return domain.CreateBetRes{}, ErrBetAmountTooHigh
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.Outcomes) > int(settingsList.MaxNumberOfOutcomes) {
|
||||||
|
s.mongoLogger.Info("too many outcomes",
|
||||||
zap.Int("count", len(req.Outcomes)),
|
zap.Int("count", len(req.Outcomes)),
|
||||||
zap.Int64("user_id", userID),
|
zap.Int64("user_id", userID),
|
||||||
)
|
)
|
||||||
|
|
@ -224,6 +250,16 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
outcomes = append(outcomes, newOutcome)
|
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)
|
outcomesHash, err := generateOutcomeHash(outcomes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to generate outcome hash",
|
s.mongoLogger.Error("failed to generate outcome hash",
|
||||||
|
|
@ -234,14 +270,6 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||||
if err != nil {
|
|
||||||
return domain.CreateBetRes{}, err
|
|
||||||
}
|
|
||||||
if count >= 2 {
|
|
||||||
return domain.CreateBetRes{}, fmt.Errorf("bet already pleaced twice")
|
|
||||||
}
|
|
||||||
|
|
||||||
cashoutID, err := s.GenerateCashoutID()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to generate cashout ID",
|
s.mongoLogger.Error("failed to generate cashout ID",
|
||||||
zap.Int64("user_id", userID),
|
zap.Int64("user_id", userID),
|
||||||
|
|
@ -249,6 +277,9 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
)
|
)
|
||||||
return domain.CreateBetRes{}, err
|
return domain.CreateBetRes{}, err
|
||||||
}
|
}
|
||||||
|
if count >= 2 {
|
||||||
|
return domain.CreateBetRes{}, fmt.Errorf("bet already placed twice")
|
||||||
|
}
|
||||||
|
|
||||||
fastCode := helpers.GenerateFastCode()
|
fastCode := helpers.GenerateFastCode()
|
||||||
amount := req.Amount + (req.Amount * calculateAccumulator(len(outcomes)))
|
amount := req.Amount + (req.Amount * calculateAccumulator(len(outcomes)))
|
||||||
|
|
@ -257,15 +288,14 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
Amount: domain.ToCurrency(amount),
|
Amount: domain.ToCurrency(amount),
|
||||||
TotalOdds: totalOdds,
|
TotalOdds: totalOdds,
|
||||||
Status: domain.OUTCOME_STATUS_PENDING,
|
Status: domain.OUTCOME_STATUS_PENDING,
|
||||||
FullName: req.FullName,
|
|
||||||
PhoneNumber: req.PhoneNumber,
|
|
||||||
CashoutID: cashoutID,
|
|
||||||
OutcomesHash: outcomesHash,
|
OutcomesHash: outcomesHash,
|
||||||
FastCode: fastCode,
|
FastCode: fastCode,
|
||||||
|
UserID: userID,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch role {
|
switch role {
|
||||||
case domain.RoleCashier:
|
case domain.RoleCashier:
|
||||||
|
newBet.IsShopBet = true
|
||||||
branch, err := s.branchSvc.GetBranchByCashier(ctx, userID)
|
branch, err := s.branchSvc.GetBranchByCashier(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to get branch by cashier",
|
s.mongoLogger.Error("failed to get branch by cashier",
|
||||||
|
|
@ -275,30 +305,20 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
return domain.CreateBetRes{}, err
|
return domain.CreateBetRes{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
deductedAmount := req.Amount / 10
|
err = s.DeductBetFromBranchWallet(ctx, req.Amount, branch.WalletID, branch.CompanyID, userID)
|
||||||
_, 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 {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to deduct from wallet",
|
s.mongoLogger.Error("wallet deduction for bet failed",
|
||||||
zap.Int64("wallet_id", branch.WalletID),
|
zap.String("role", string(role)),
|
||||||
zap.Float32("amount", deductedAmount),
|
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
return domain.CreateBetRes{}, 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:
|
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 {
|
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),
|
zap.Int64("user_id", userID),
|
||||||
)
|
)
|
||||||
return domain.CreateBetRes{}, ErrBranchIDRequired
|
return domain.CreateBetRes{}, ErrBranchIDRequired
|
||||||
|
|
@ -313,87 +333,42 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
return domain.CreateBetRes{}, err
|
return domain.CreateBetRes{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
deductedAmount := req.Amount / 10
|
if branch.BranchManagerID != userID {
|
||||||
_, err = s.walletSvc.DeductFromWallet(ctx, branch.WalletID, domain.ToCurrency(deductedAmount), domain.BranchWalletType, domain.ValidInt64{
|
s.mongoLogger.Warn("unauthorized branch for branch manager",
|
||||||
Value: userID,
|
zap.Int64("branch_id", *req.BranchID),
|
||||||
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),
|
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
return domain.CreateBetRes{}, err
|
return domain.CreateBetRes{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newBet.BranchID = domain.ValidInt64{Value: branch.ID, Valid: true}
|
if companyID.Valid && branch.CompanyID == companyID.Value {
|
||||||
newBet.CompanyID = domain.ValidInt64{Value: branch.CompanyID, Valid: true}
|
s.mongoLogger.Warn("unauthorized company",
|
||||||
newBet.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
zap.Int64("branch_id", *req.BranchID),
|
||||||
newBet.IsShopBet = true
|
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:
|
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 {
|
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.Int64("user_id", userID),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
return domain.CreateBetRes{}, 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:
|
default:
|
||||||
s.mongoLogger.Error("unknown role type",
|
s.mongoLogger.Error("unknown role type",
|
||||||
zap.String("role", string(role)),
|
zap.String("role", string(role)),
|
||||||
|
|
@ -428,6 +403,100 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
return res, nil
|
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) {
|
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
|
var newOdds []domain.CreateBetOutcome
|
||||||
|
|
@ -638,26 +707,38 @@ func (s *Service) PlaceRandomBet(ctx context.Context, userID, branchID int64, le
|
||||||
|
|
||||||
// s.logger.Info("Generated Random bet Outcome", "randomOdds", len(randomOdds))
|
// s.logger.Info("Generated Random bet Outcome", "randomOdds", len(randomOdds))
|
||||||
|
|
||||||
var cashoutID string
|
outcomesHash, err := generateOutcomeHash(randomOdds)
|
||||||
|
|
||||||
cashoutID, err = s.GenerateCashoutID()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("Failed to generate cash out ID",
|
s.mongoLogger.Error("failed to generate outcome hash",
|
||||||
zap.Int64("userID", userID),
|
zap.Int64("user_id", userID),
|
||||||
zap.Int64("branchID", branchID))
|
zap.Error(err),
|
||||||
|
)
|
||||||
return domain.CreateBetRes{}, 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{
|
newBet := domain.CreateBet{
|
||||||
Amount: domain.ToCurrency(123.5),
|
Amount: domain.ToCurrency(123.5),
|
||||||
TotalOdds: totalOdds,
|
TotalOdds: totalOdds,
|
||||||
Status: domain.OUTCOME_STATUS_PENDING,
|
Status: domain.OUTCOME_STATUS_PENDING,
|
||||||
FullName: "test" + randomNumber,
|
UserID: userID,
|
||||||
PhoneNumber: "0900000000",
|
IsShopBet: true,
|
||||||
CashoutID: cashoutID,
|
FastCode: fastCode,
|
||||||
BranchID: domain.ValidInt64{Valid: true, Value: branchID},
|
|
||||||
UserID: domain.ValidInt64{Valid: true, Value: userID},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bet, err := s.CreateBet(ctx, newBet)
|
bet, err := s.CreateBet(ctx, newBet)
|
||||||
|
|
@ -702,17 +783,10 @@ func (s *Service) CreateBetOutcome(ctx context.Context, outcomes []domain.Create
|
||||||
func (s *Service) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error) {
|
func (s *Service) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error) {
|
||||||
return s.betStore.GetBetByID(ctx, id)
|
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) {
|
func (s *Service) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
|
||||||
return s.betStore.GetAllBets(ctx, filter)
|
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) {
|
func (s *Service) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error) {
|
||||||
return s.betStore.GetBetByUserID(ctx, UserID)
|
return s.betStore.GetBetByUserID(ctx, UserID)
|
||||||
}
|
}
|
||||||
|
|
@ -1103,3 +1177,27 @@ func calculateAccumulator(outcomesCount int) float32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,5 @@ type Service interface {
|
||||||
// GetAndStoreMatchResult(ctx context.Context, eventID string) error
|
// GetAndStoreMatchResult(ctx context.Context, eventID string) error
|
||||||
UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error
|
UpdateFinalScore(ctx context.Context, eventID, fullScore string, status domain.EventStatus) error
|
||||||
UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error
|
UpdateEventStatus(ctx context.Context, eventID string, status domain.EventStatus) error
|
||||||
|
UpdateFlagged(ctx context.Context, eventID string, flagged bool) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -369,6 +369,10 @@ func (s *service) UpdateEventStatus(ctx context.Context, eventID string, status
|
||||||
return s.store.UpdateEventStatus(ctx, eventID, status)
|
return s.store.UpdateEventStatus(ctx, eventID, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *service) UpdateFlagged(ctx context.Context, eventID string, flagged bool) error {
|
||||||
|
return s.store.UpdateFlagged(ctx, eventID, flagged)
|
||||||
|
}
|
||||||
|
|
||||||
// func (s *service) GetAndStoreMatchResult(ctx context.Context, eventID string) error {
|
// func (s *service) GetAndStoreMatchResult(ctx context.Context, eventID string) error {
|
||||||
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.token, eventID)
|
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.token, eventID)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,19 @@ func New(repo repository.ReportedIssueRepository) *Service {
|
||||||
return &Service{repo: repo}
|
return &Service{repo: repo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.ReportedIssue) (domain.ReportedIssue, error) {
|
func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.ReportedIssueReq, userID int64, role domain.Role) (domain.ReportedIssue, error) {
|
||||||
|
|
||||||
|
// metadata, err := json.Marshal(issue.Metadata)
|
||||||
|
// if err != nil {
|
||||||
|
// return domain.ReportedIssue{}, err
|
||||||
|
// }
|
||||||
params := dbgen.CreateReportedIssueParams{
|
params := dbgen.CreateReportedIssueParams{
|
||||||
// Map fields from domain.ReportedIssue to dbgen.CreateReportedIssueParams here.
|
UserID: userID,
|
||||||
// Example:
|
UserRole: string(role),
|
||||||
// Title: issue.Title,
|
Subject: issue.Subject,
|
||||||
// Description: issue.Description,
|
Description: issue.Description,
|
||||||
// CustomerID: issue.CustomerID,
|
IssueType: string(issue.IssueType),
|
||||||
// Status: issue.Status,
|
// Metadata: metadata,
|
||||||
// Add other fields as necessary.
|
|
||||||
}
|
}
|
||||||
dbIssue, err := s.repo.CreateReportedIssue(ctx, params)
|
dbIssue, err := s.repo.CreateReportedIssue(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -36,17 +40,20 @@ func (s *Service) CreateReportedIssue(ctx context.Context, issue domain.Reported
|
||||||
ID: dbIssue.ID,
|
ID: dbIssue.ID,
|
||||||
Subject: dbIssue.Subject,
|
Subject: dbIssue.Subject,
|
||||||
Description: dbIssue.Description,
|
Description: dbIssue.Description,
|
||||||
CustomerID: dbIssue.CustomerID,
|
UserID: dbIssue.UserID,
|
||||||
Status: dbIssue.Status,
|
UserRole: domain.Role(dbIssue.UserRole),
|
||||||
|
Status: domain.ReportedIssueStatus(dbIssue.Status),
|
||||||
|
IssueType: domain.ReportedIssueType(dbIssue.IssueType),
|
||||||
CreatedAt: dbIssue.CreatedAt.Time,
|
CreatedAt: dbIssue.CreatedAt.Time,
|
||||||
UpdatedAt: dbIssue.UpdatedAt.Time,
|
UpdatedAt: dbIssue.UpdatedAt.Time,
|
||||||
|
|
||||||
// Add other fields as necessary
|
// Add other fields as necessary
|
||||||
}
|
}
|
||||||
return reportedIssue, nil
|
return reportedIssue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetIssuesForCustomer(ctx context.Context, customerID int64, limit, offset int) ([]domain.ReportedIssue, error) {
|
func (s *Service) GetIssuesForUser(ctx context.Context, userID int64, limit, offset int) ([]domain.ReportedIssue, error) {
|
||||||
dbIssues, err := s.repo.ListReportedIssuesByCustomer(ctx, customerID, int32(limit), int32(offset))
|
dbIssues, err := s.repo.ListReportedIssuesByUser(ctx, userID, int32(limit), int32(offset))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -56,8 +63,10 @@ func (s *Service) GetIssuesForCustomer(ctx context.Context, customerID int64, li
|
||||||
ID: dbIssue.ID,
|
ID: dbIssue.ID,
|
||||||
Subject: dbIssue.Subject,
|
Subject: dbIssue.Subject,
|
||||||
Description: dbIssue.Description,
|
Description: dbIssue.Description,
|
||||||
CustomerID: dbIssue.CustomerID,
|
UserID: dbIssue.UserID,
|
||||||
Status: dbIssue.Status,
|
UserRole: domain.Role(dbIssue.UserRole),
|
||||||
|
Status: domain.ReportedIssueStatus(dbIssue.Status),
|
||||||
|
IssueType: domain.ReportedIssueType(dbIssue.IssueType),
|
||||||
CreatedAt: dbIssue.CreatedAt.Time,
|
CreatedAt: dbIssue.CreatedAt.Time,
|
||||||
UpdatedAt: dbIssue.UpdatedAt.Time,
|
UpdatedAt: dbIssue.UpdatedAt.Time,
|
||||||
// Add other fields as necessary
|
// Add other fields as necessary
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ func (s *Service) GetBetAnalysis(ctx context.Context, filter domain.ReportFilter
|
||||||
s.logger.Error("failed to get sport popularity", "error", err)
|
s.logger.Error("failed to get sport popularity", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get market popularity
|
// Get market popularity
|
||||||
marketPopularity, err := s.betStore.GetMarketPopularity(ctx, filter)
|
marketPopularity, err := s.betStore.GetMarketPopularity(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -674,7 +674,7 @@ func (s *Service) fetchReportData(ctx context.Context, period string) (domain.Re
|
||||||
totalCashBacks = 0
|
totalCashBacks = 0
|
||||||
}
|
}
|
||||||
companyReports = append(companyReports, domain.CompanyReport{
|
companyReports = append(companyReports, domain.CompanyReport{
|
||||||
CompanyID: row.CompanyID.Int64,
|
CompanyID: row.CompanyID,
|
||||||
CompanyName: row.CompanyName,
|
CompanyName: row.CompanyName,
|
||||||
TotalBets: row.TotalBets,
|
TotalBets: row.TotalBets,
|
||||||
TotalCashIn: totalCashIn,
|
TotalCashIn: totalCashIn,
|
||||||
|
|
@ -727,7 +727,7 @@ func (s *Service) fetchReportData(ctx context.Context, period string) (domain.Re
|
||||||
totalCashBacks = 0
|
totalCashBacks = 0
|
||||||
}
|
}
|
||||||
branchReports = append(branchReports, domain.BranchReport{
|
branchReports = append(branchReports, domain.BranchReport{
|
||||||
BranchID: row.BranchID.Int64,
|
BranchID: row.BranchID,
|
||||||
BranchName: row.BranchName,
|
BranchName: row.BranchName,
|
||||||
CompanyID: row.CompanyID,
|
CompanyID: row.CompanyID,
|
||||||
TotalBets: row.TotalBets,
|
TotalBets: row.TotalBets,
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ var (
|
||||||
ErrTicketAmountTooHigh = errors.New("Cannot create a ticket with an amount above limit")
|
ErrTicketAmountTooHigh = errors.New("Cannot create a ticket with an amount above limit")
|
||||||
ErrTicketLimitForSingleUser = errors.New("Number of Ticket Limit reached")
|
ErrTicketLimitForSingleUser = errors.New("Number of Ticket Limit reached")
|
||||||
ErrTicketWinningTooHigh = errors.New("Total Winnings over set limit")
|
ErrTicketWinningTooHigh = errors.New("Total Winnings over set limit")
|
||||||
|
ErrInvalidAmount = errors.New("Invalid amount")
|
||||||
ErrRawOddInvalid = errors.New("Prematch Raw Odd is Invalid")
|
ErrRawOddInvalid = errors.New("Prematch Raw Odd is Invalid")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
|
@ -34,7 +34,7 @@ type Service struct {
|
||||||
eventSvc event.Service
|
eventSvc event.Service
|
||||||
prematchSvc odds.ServiceImpl
|
prematchSvc odds.ServiceImpl
|
||||||
mongoLogger *zap.Logger
|
mongoLogger *zap.Logger
|
||||||
settingSvc settings.Service
|
settingSvc settings.Service
|
||||||
notificationSvc *notificationservice.Service
|
notificationSvc *notificationservice.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ func NewService(
|
||||||
eventSvc: eventSvc,
|
eventSvc: eventSvc,
|
||||||
prematchSvc: prematchSvc,
|
prematchSvc: prematchSvc,
|
||||||
mongoLogger: mongoLogger,
|
mongoLogger: mongoLogger,
|
||||||
settingSvc: settingSvc,
|
settingSvc: settingSvc,
|
||||||
notificationSvc: notificationSvc,
|
notificationSvc: notificationSvc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +167,10 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if req.Amount < 1 {
|
||||||
|
return domain.Ticket{}, 0, ErrInvalidAmount
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see if the amount is above a set limit
|
// Check to see if the amount is above a set limit
|
||||||
if req.Amount > settingsList.BetAmountLimit.Float32() {
|
if req.Amount > settingsList.BetAmountLimit.Float32() {
|
||||||
return domain.Ticket{}, 0, ErrTicketAmountTooHigh
|
return domain.Ticket{}, 0, ErrTicketAmountTooHigh
|
||||||
|
|
@ -183,7 +187,6 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
|
||||||
|
|
||||||
// Check to see how many tickets a single anonymous user has created
|
// Check to see how many tickets a single anonymous user has created
|
||||||
if count > settingsList.DailyTicketPerIP {
|
if count > settingsList.DailyTicketPerIP {
|
||||||
|
|
||||||
return domain.Ticket{}, 0, ErrTicketLimitForSingleUser
|
return domain.Ticket{}, 0, ErrTicketLimitForSingleUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,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
|
// Check to see if the total winning amount is over a set limit
|
||||||
if totalWinnings > settingsList.TotalWinningLimit.Float32() {
|
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("Total Odds", totalOdds),
|
||||||
zap.Float32("amount", req.Amount),
|
zap.Float32("amount", req.Amount),
|
||||||
zap.Float32("limit", settingsList.TotalWinningLimit.Float32()))
|
zap.Float32("limit", settingsList.TotalWinningLimit.Float32()))
|
||||||
|
|
@ -276,3 +279,24 @@ func (s *Service) DeleteTicket(ctx context.Context, id int64) error {
|
||||||
func (s *Service) DeleteOldTickets(ctx context.Context) error {
|
func (s *Service) DeleteOldTickets(ctx context.Context) error {
|
||||||
return s.ticketStore.DeleteOldTickets(ctx)
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,9 @@ func (s *Service) CreateShopBet(ctx context.Context, userID int64, role domain.R
|
||||||
}
|
}
|
||||||
|
|
||||||
newBet, err := s.betSvc.PlaceBet(ctx, domain.CreateBetReq{
|
newBet, err := s.betSvc.PlaceBet(ctx, domain.CreateBetReq{
|
||||||
Outcomes: req.Outcomes,
|
Outcomes: req.Outcomes,
|
||||||
Amount: req.Amount,
|
Amount: req.Amount,
|
||||||
FullName: req.FullName,
|
}, userID, role, userCompanyID)
|
||||||
PhoneNumber: req.PhoneNumber,
|
|
||||||
BranchID: branchID,
|
|
||||||
}, userID, role)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.ShopBet{}, err
|
return domain.ShopBet{}, err
|
||||||
|
|
|
||||||
|
|
@ -24,22 +24,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
||||||
spec string
|
spec string
|
||||||
task func()
|
task func()
|
||||||
}{
|
}{
|
||||||
{
|
// {
|
||||||
spec: "0 0 * * * *", // Every 1 hour
|
// spec: "0 0 * * * *", // Every 1 hour
|
||||||
task: func() {
|
// task: func() {
|
||||||
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||||||
log.Printf("FetchUpcomingEvents error: %v", err)
|
// log.Printf("FetchUpcomingEvents error: %v", err)
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
// spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
||||||
task: func() {
|
// task: func() {
|
||||||
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||||
log.Printf("FetchNonLiveOdds error: %v", err)
|
// log.Printf("FetchNonLiveOdds error: %v", err)
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
spec: "0 */5 * * * *", // Every 5 Minutes
|
spec: "0 */5 * * * *", // Every 5 Minutes
|
||||||
task: func() {
|
task: func() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -31,28 +32,32 @@ type CreateAdminReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /admin [post]
|
// @Router /api/v1/admin [post]
|
||||||
func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
||||||
var companyID domain.ValidInt64
|
var companyID domain.ValidInt64
|
||||||
var req CreateAdminReq
|
var req CreateAdminReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int64("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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",
|
h.mongoLoggerSvc.Error("validation failed for CreateAdmin request",
|
||||||
zap.Int64("status_code", fiber.StatusBadRequest),
|
zap.Int64("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if req.CompanyID == nil {
|
||||||
|
|
@ -69,7 +74,7 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{
|
companyID = domain.ValidInt64{
|
||||||
Value: *req.CompanyID,
|
Value: *req.CompanyID,
|
||||||
|
|
@ -95,13 +100,16 @@ func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if req.CompanyID != nil {
|
||||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||||
ID: *req.CompanyID,
|
ID: *req.CompanyID,
|
||||||
AdminID: &newUser.ID,
|
AdminID: domain.ValidInt64{
|
||||||
|
Value: newUser.ID,
|
||||||
|
Valid: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("failed to update company with new admin",
|
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.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /admin [get]
|
// @Router /api/v1/admin [get]
|
||||||
func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||||
|
|
||||||
searchQuery := c.Query("query")
|
searchQuery := c.Query("query")
|
||||||
|
|
@ -166,8 +174,8 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.logger.Info("invalid start_time format", "error", err)
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||||
}
|
}
|
||||||
createdBefore = domain.ValidTime{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -180,8 +188,8 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.logger.Info("invalid start_time format", "error", err)
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||||
}
|
}
|
||||||
createdAfter = domain.ValidTime{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -209,12 +217,16 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||||
|
|
||||||
valErrs, ok := h.validator.Validate(c, filter)
|
valErrs, ok := h.validator.Validate(c, filter)
|
||||||
if !ok {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
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.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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))
|
result := make([]AdminRes, len(admins))
|
||||||
|
|
@ -241,7 +253,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
||||||
userIDstr := c.Params("id")
|
userIDstr := c.Params("id")
|
||||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||||
|
|
@ -294,7 +306,7 @@ func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
|
|
@ -305,7 +317,7 @@ func (h *Handler) GetAdminByID(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
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.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if err == authentication.ErrRefreshTokenNotFound {
|
||||||
lastLogin = &user.CreatedAt
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -365,7 +377,7 @@ type updateAdminReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
||||||
var req updateAdminReq
|
var req updateAdminReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
|
@ -374,29 +386,33 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
var errMsg string
|
||||||
|
for field, msg := range valErrs {
|
||||||
|
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||||
|
}
|
||||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - validation errors",
|
h.mongoLoggerSvc.Error("UpdateAdmin failed - validation errors",
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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")
|
AdminIDStr := c.Params("id")
|
||||||
AdminID, err := strconv.ParseInt(AdminIDStr, 10, 64)
|
AdminID, err := strconv.ParseInt(AdminIDStr, 10, 64)
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.String("admin_id_param", AdminIDStr),
|
zap.String("admin_id_param", AdminIDStr),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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
|
var companyID domain.ValidInt64
|
||||||
|
|
@ -430,13 +446,16 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if req.CompanyID != nil {
|
||||||
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
_, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{
|
||||||
ID: *req.CompanyID,
|
ID: *req.CompanyID,
|
||||||
AdminID: &AdminID,
|
AdminID: domain.ValidInt64{
|
||||||
|
Value: AdminID,
|
||||||
|
Valid: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("UpdateAdmin failed to update company",
|
h.mongoLoggerSvc.Error("UpdateAdmin failed to update company",
|
||||||
|
|
@ -445,7 +464,7 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||||
|
|
@ -36,41 +37,47 @@ type loginCustomerRes struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
||||||
var req loginCustomerReq
|
var req loginCustomerReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||||
h.mongoLoggerSvc.Error("LoginCustomer validation failed",
|
var errMsg string
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
for field, msg := range valErrs {
|
||||||
zap.Any("request", req),
|
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||||
zap.Time("timestamp", time.Now()),
|
}
|
||||||
)
|
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Request")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
successRes, err := h.authSvc.Login(c.Context(), req.Email, req.PhoneNumber, req.Password)
|
successRes, err := h.authSvc.Login(c.Context(), req.Email, req.PhoneNumber, req.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Info("Login attempt failed",
|
|
||||||
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 {
|
switch {
|
||||||
case errors.Is(err, authentication.ErrInvalidPassword), errors.Is(err, authentication.ErrUserNotFound):
|
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()),
|
||||||
|
)
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
|
||||||
case errors.Is(err, authentication.ErrUserSuspended):
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "User login has been locked")
|
||||||
default:
|
default:
|
||||||
h.mongoLoggerSvc.Error("Login failed",
|
h.mongoLoggerSvc.Error("Login failed",
|
||||||
|
|
@ -125,7 +132,7 @@ type refreshToken struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||||
|
|
||||||
type loginCustomerRes struct {
|
type loginCustomerRes struct {
|
||||||
|
|
@ -136,35 +143,47 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req refreshToken
|
var req refreshToken
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
refreshToken, err := h.authSvc.RefreshToken(c.Context(), req.RefreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Info("Refresh token attempt failed",
|
|
||||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
|
||||||
zap.String("refresh_token", req.RefreshToken),
|
|
||||||
zap.Error(err),
|
|
||||||
zap.Time("timestamp", time.Now()),
|
|
||||||
)
|
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, authentication.ErrExpiredToken):
|
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()),
|
||||||
|
)
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
||||||
case errors.Is(err, authentication.ErrRefreshTokenNotFound):
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Refresh token not found")
|
||||||
default:
|
default:
|
||||||
h.mongoLoggerSvc.Error("Refresh token failed",
|
h.mongoLoggerSvc.Error("Refresh token failed",
|
||||||
|
|
@ -184,7 +203,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
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.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{
|
res := loginCustomerRes{
|
||||||
|
|
@ -204,7 +223,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||||
Role: string(user.Role),
|
Role: string(user.Role),
|
||||||
}
|
}
|
||||||
|
|
||||||
h.mongoLoggerSvc.Info("Refresh token successful",
|
h.mongoLoggerSvc.Info("Token Refreshed Successfully",
|
||||||
zap.Int("status_code", fiber.StatusOK),
|
zap.Int("status_code", fiber.StatusOK),
|
||||||
zap.Int64("user_id", user.ID),
|
zap.Int64("user_id", user.ID),
|
||||||
zap.String("role", string(user.Role)),
|
zap.String("role", string(user.Role)),
|
||||||
|
|
@ -229,39 +248,53 @@ type logoutReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) LogOutCustomer(c *fiber.Ctx) error {
|
||||||
var req logoutReq
|
var req logoutReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
err := h.authSvc.Logout(c.Context(), req.RefreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Info("Logout attempt failed",
|
|
||||||
zap.Int("status_code", fiber.StatusUnauthorized),
|
|
||||||
zap.String("refresh_token", req.RefreshToken),
|
|
||||||
zap.Error(err),
|
|
||||||
zap.Time("timestamp", time.Now()),
|
|
||||||
)
|
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, authentication.ErrExpiredToken):
|
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()),
|
||||||
|
)
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
return fiber.NewError(fiber.StatusUnauthorized, "The refresh token has expired")
|
||||||
case errors.Is(err, authentication.ErrRefreshTokenNotFound):
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Refresh token not found")
|
||||||
default:
|
default:
|
||||||
h.mongoLoggerSvc.Error("Logout failed",
|
h.mongoLoggerSvc.Error("Logout failed",
|
||||||
|
|
@ -269,7 +302,7 @@ func (h *Handler) LogOutCustomer(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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
|
// @Success 200 {object} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
var req domain.CreateBetReq
|
var req domain.CreateBetReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
|
@ -35,16 +36,18 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("Failed to create bet",
|
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.Int64("user_id", userID),
|
||||||
|
zap.String("role", string(role)),
|
||||||
zap.Time("timestamp", time.Now()),
|
zap.Time("timestamp", time.Now()),
|
||||||
)
|
)
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create bet:"+err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
h.mongoLoggerSvc.Info("Bet created successfully",
|
h.mongoLoggerSvc.Info("Bet created successfully",
|
||||||
|
|
@ -66,10 +69,11 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.BetRes
|
// @Success 200 {object} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
var req struct {
|
var req struct {
|
||||||
FastCode string `json:"fast_code"`
|
FastCode string `json:"fast_code"`
|
||||||
|
|
@ -82,27 +86,29 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
bet, err := h.betSvc.GetBetByFastCode(c.Context(), req.FastCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("falied to get bet with fast code",
|
h.mongoLoggerSvc.Info("failed to get bet with fast code",
|
||||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
zap.String("fast_code", req.FastCode),
|
||||||
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
outcomes, err := h.betSvc.GetBetOutcomeByBetID(c.Context(), bet.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("falied to get BetOutcomes by BetID",
|
h.mongoLoggerSvc.Info("failed to get BetOutcomes by BetID",
|
||||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
zap.Int64("bet_id", bet.ID),
|
||||||
zap.Error(err),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{}
|
bet_outcomes := []domain.CreateBetOutcomeReq{}
|
||||||
|
|
@ -142,30 +148,37 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
||||||
PhoneNumber: user.PhoneNumber,
|
PhoneNumber: user.PhoneNumber,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.CreateBetInternal(c, newReq, userID, role)
|
res, err := h.CreateBetInternal(c, newReq, userID, role, companyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("Failed to create bet",
|
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.Int64("user_id", userID),
|
||||||
|
zap.String("role", string(role)),
|
||||||
|
zap.Any("newReq", newReq),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
||||||
|
|
||||||
// TODO: amount added for fast code owner can be fetched from settings in db
|
// 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{},
|
_, 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()))
|
domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Added %v to static wallet by referring using fast_code", amount.Float32()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("Failed to add reward to static bet",
|
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.Int64("user_id", userID),
|
||||||
|
zap.Float32("amount", amount.Float32()),
|
||||||
|
zap.Int64("static wallet_id", wallet.StaticID),
|
||||||
zap.Time("timestamp", time.Now()),
|
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",
|
h.mongoLoggerSvc.Info("Bet created successfully",
|
||||||
|
|
@ -176,7 +189,7 @@ func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", res, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.mongoLoggerSvc.Error("CreateBet validation failed",
|
h.mongoLoggerSvc.Error("CreateBet validation failed",
|
||||||
|
|
@ -187,19 +200,30 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
||||||
return domain.CreateBetRes{}, fmt.Errorf("%s", valErrs)
|
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 {
|
if err != nil {
|
||||||
|
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()),
|
||||||
|
)
|
||||||
|
return domain.CreateBetRes{}, fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
h.mongoLoggerSvc.Error("PlaceBet failed",
|
h.mongoLoggerSvc.Error("PlaceBet failed",
|
||||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||||
|
zap.Int64("userID", userID),
|
||||||
|
zap.Int64("companyID", companyID.Value),
|
||||||
|
zap.String("role", string(role)),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
return domain.CreateBetRes{}, fiber.NewError(fiber.StatusInternalServerError, "Unable to create bet")
|
return domain.CreateBetRes{}, fiber.NewError(fiber.StatusInternalServerError, "Unable to create bet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,28 +240,28 @@ func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userI
|
||||||
// @Success 200 {object} domain.BetRes
|
// @Success 200 {object} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
|
|
||||||
leagueIDQuery, err := strconv.Atoi(c.Query("league_id"))
|
leagueIDQuery, err := strconv.Atoi(c.Query("league_id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("invalid league id",
|
h.mongoLoggerSvc.Info("invalid league id",
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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"))
|
sportIDQuery, err := strconv.Atoi(c.Query("sport_id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("invalid sport id",
|
h.mongoLoggerSvc.Info("invalid sport id",
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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")
|
firstStartTimeQuery := c.Query("first_start_time")
|
||||||
|
|
@ -256,12 +280,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||||
if firstStartTimeQuery != "" {
|
if firstStartTimeQuery != "" {
|
||||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{
|
firstStartTime = domain.ValidTime{
|
||||||
Value: firstStartTimeParsed,
|
Value: firstStartTimeParsed,
|
||||||
|
|
@ -273,12 +298,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||||
if lastStartTimeQuery != "" {
|
if lastStartTimeQuery != "" {
|
||||||
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{
|
lastStartTime = domain.ValidTime{
|
||||||
Value: lastStartTimeParsed,
|
Value: lastStartTimeParsed,
|
||||||
|
|
@ -288,38 +314,45 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req domain.RandomBetReq
|
var req domain.RandomBetReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
var errMsg string
|
||||||
|
for field, msg := range valErrs {
|
||||||
|
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||||
|
}
|
||||||
h.mongoLoggerSvc.Error("RandomBet validation failed",
|
h.mongoLoggerSvc.Error("RandomBet validation failed",
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Any("validation_errors", valErrs),
|
zap.Any("validation_errors", valErrs),
|
||||||
zap.Time("timestamp", time.Now()),
|
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
|
var res domain.CreateBetRes
|
||||||
for i := 0; i < int(req.NumberOfBets); i++ {
|
for i := 0; i < int(req.NumberOfBets); i++ {
|
||||||
res, err = h.betSvc.PlaceRandomBet(c.Context(), userID, req.BranchID, leagueID, sportID, firstStartTime, lastStartTime)
|
res, err = h.betSvc.PlaceRandomBet(c.Context(), userID, req.BranchID, leagueID, sportID, firstStartTime, lastStartTime)
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusInternalServerError),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
zap.Time("timestamp", time.Now()),
|
||||||
)
|
)
|
||||||
switch err {
|
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet:"+err.Error())
|
||||||
case bet.ErrNoEventsAvailable:
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "No events found")
|
|
||||||
}
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,23 +374,24 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {array} domain.BetRes
|
// @Success 200 {array} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
// companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
branchID := c.Locals("branch_id").(domain.ValidInt64)
|
// branchID := c.Locals("branch_id").(domain.ValidInt64)
|
||||||
|
|
||||||
var isShopBet domain.ValidBool
|
var isShopBet domain.ValidBool
|
||||||
isShopBetQuery := c.Query("is_shop")
|
isShopBetQuery := c.Query("is_shop")
|
||||||
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
||||||
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusBadRequest),
|
||||||
|
zap.String("is_shop", isShopBetQuery),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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{
|
isShopBet = domain.ValidBool{
|
||||||
Value: isShopBetParse,
|
Value: isShopBetParse,
|
||||||
|
|
@ -376,8 +410,13 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -390,8 +429,13 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -399,24 +443,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{
|
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
|
||||||
BranchID: branchID,
|
|
||||||
CompanyID: companyID,
|
|
||||||
IsShopBet: isShopBet,
|
IsShopBet: isShopBet,
|
||||||
Query: searchString,
|
Query: searchString,
|
||||||
CreatedBefore: createdBefore,
|
CreatedBefore: createdBefore,
|
||||||
CreatedAfter: createdAfter,
|
CreatedAfter: createdAfter,
|
||||||
})
|
})
|
||||||
if err != nil {
|
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.Int("status_code", fiber.StatusInternalServerError),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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))
|
res := make([]domain.BetRes, len(bets))
|
||||||
|
|
@ -424,11 +463,6 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||||
res[i] = domain.ConvertBet(bet)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "All bets retrieved successfully", res, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,12 +476,12 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.BetRes
|
// @Success 200 {object} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||||
betID := c.Params("id")
|
betID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(betID, 10, 64)
|
id, err := strconv.ParseInt(betID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("Invalid bet ID",
|
h.mongoLoggerSvc.Info("Invalid bet ID",
|
||||||
zap.String("betID", betID),
|
zap.String("betID", betID),
|
||||||
zap.Int("status_code", fiber.StatusBadRequest),
|
zap.Int("status_code", fiber.StatusBadRequest),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
|
|
@ -458,7 +492,7 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
bet, err := h.betSvc.GetBetByID(c.Context(), id)
|
bet, err := h.betSvc.GetBetByID(c.Context(), id)
|
||||||
if err != nil {
|
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.Int64("betID", id),
|
||||||
zap.Int("status_code", fiber.StatusNotFound),
|
zap.Int("status_code", fiber.StatusNotFound),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
|
|
@ -469,47 +503,11 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
res := domain.ConvertBet(bet)
|
res := domain.ConvertBet(bet)
|
||||||
|
|
||||||
h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
||||||
zap.Int64("betID", id),
|
// zap.Int64("betID", id),
|
||||||
zap.Int("status_code", fiber.StatusOK),
|
// zap.Int("status_code", fiber.StatusOK),
|
||||||
zap.Time("timestamp", time.Now()),
|
// 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()),
|
|
||||||
)
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -529,7 +527,7 @@ type UpdateCashOutReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
||||||
type UpdateCashOutReq struct {
|
type UpdateCashOutReq struct {
|
||||||
CashedOut bool `json:"cashed_out" validate:"required" example:"true"`
|
CashedOut bool `json:"cashed_out" validate:"required" example:"true"`
|
||||||
|
|
@ -555,11 +553,15 @@ func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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 {
|
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)
|
err = h.betSvc.UpdateCashOut(c.Context(), id, req.CashedOut)
|
||||||
|
|
@ -592,7 +594,7 @@ func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
||||||
betID := c.Params("id")
|
betID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(betID, 10, 64)
|
id, err := strconv.ParseInt(betID, 10, 64)
|
||||||
|
|
@ -614,7 +616,7 @@ func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.Time("timestamp", time.Now()),
|
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",
|
h.mongoLoggerSvc.Info("Bet removed successfully",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) CreateBonusMultiplier(c *fiber.Ctx) error {
|
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 {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("failed to parse bonus multiplier", "error", err)
|
h.logger.Error("failed to parse bonus multiplier request", "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())
|
||||||
}
|
}
|
||||||
|
|
||||||
// currently only one multiplier is allowed
|
// 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())
|
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to get bonus multiplier", "error", err)
|
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 {
|
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 {
|
if err := h.bonusSvc.CreateBonusMultiplier(c.Context(), req.Multiplier, req.BalanceCap); err != nil {
|
||||||
h.logger.Error("failed to create bonus multiplier", "error", err)
|
h.mongoLoggerSvc.Error("failed to create bonus multiplier",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "failed to create bonus mulitplier", nil, nil)
|
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 {
|
func (h *Handler) GetBonusMultiplier(c *fiber.Ctx) error {
|
||||||
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
|
multipliers, err := h.bonusSvc.GetBonusMultiplier(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to get bonus multiplier", "error", err)
|
h.mongoLoggerSvc.Info("failed to get bonus multiplier",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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 {
|
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 {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("failed to parse bonus multiplier", "error", err)
|
h.mongoLoggerSvc.Info("failed to parse bonus multiplier",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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 {
|
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)
|
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/services/authentication"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateCashierReq struct {
|
type CreateCashierReq struct {
|
||||||
|
|
@ -32,7 +33,7 @@ type CreateCashierReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /cashiers [post]
|
// @Router /api/v1/cashiers [post]
|
||||||
func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// Get user_id from middleware
|
// Get user_id from middleware
|
||||||
|
|
@ -40,19 +41,33 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req CreateCashierReq
|
var req CreateCashierReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("RegisterUser failed", "error", err)
|
h.mongoLoggerSvc.Info("failed to parse CreateCashier request body",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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
|
// 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)
|
branch, err := h.branchSvc.GetBranchByID(c.Context(), req.BranchID)
|
||||||
|
|
||||||
if err != nil {
|
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{
|
userRequest := domain.CreateUserReq{
|
||||||
FirstName: req.FirstName,
|
FirstName: req.FirstName,
|
||||||
|
|
@ -70,14 +85,25 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
||||||
fmt.Print(req.Suspended)
|
fmt.Print(req.Suspended)
|
||||||
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest, true)
|
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CreateCashier failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to create cashier user",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
|
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)
|
err = h.branchSvc.CreateBranchCashier(c.Context(), req.BranchID, newUser.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CreateCashier failed", "error", err)
|
h.mongoLoggerSvc.Error("failed to create branch cashier",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Cashier created successfully", nil, nil)
|
||||||
|
|
||||||
|
|
@ -111,17 +137,22 @@ type GetCashierRes struct {
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param page query int false "Page number"
|
// @Param page query int false "Page number"
|
||||||
// @Param page_size query int false "Page size"
|
// @Param page_size query int false "Page size"
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {array} GetCashierRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /cashiers [get]
|
// @Router /api/v1/cashiers [get]
|
||||||
func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
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")
|
searchQuery := c.Query("query")
|
||||||
searchString := domain.ValidString{
|
searchString := domain.ValidString{
|
||||||
|
|
@ -134,8 +165,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -148,8 +184,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -174,7 +215,16 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
|
|
||||||
valErrs, ok := h.validator.Validate(c, filter)
|
valErrs, ok := h.validator.Validate(c, filter)
|
||||||
if !ok {
|
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{
|
cashiers, total, err := h.userSvc.GetAllCashiers(c.Context(), domain.UserFilter{
|
||||||
|
|
@ -183,8 +233,12 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
CreatedAfter: createdAfter,
|
CreatedAfter: createdAfter,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("GetAllCashiers failed", "error", err)
|
h.mongoLoggerSvc.Error("failed to get all cashiers",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
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))
|
var result []GetCashierRes = make([]GetCashierRes, 0, len(cashiers))
|
||||||
|
|
@ -195,8 +249,13 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
||||||
if err == authentication.ErrRefreshTokenNotFound {
|
if err == authentication.ErrRefreshTokenNotFound {
|
||||||
lastLogin = &cashier.CreatedAt
|
lastLogin = &cashier.CreatedAt
|
||||||
} else {
|
} else {
|
||||||
h.logger.Error("Failed to get user last login", "userID", cashier.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
|
||||||
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
||||||
// filter := user.Filter{
|
// filter := user.Filter{
|
||||||
|
|
@ -256,22 +315,37 @@ func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
|
||||||
stringID := c.Params("id")
|
stringID := c.Params("id")
|
||||||
cashierID, err := strconv.ParseInt(stringID, 10, 64)
|
cashierID, err := strconv.ParseInt(stringID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to fetch user using UserID", "error", err)
|
h.mongoLoggerSvc.Info("failed to parse user_id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
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)
|
user, err := h.userSvc.GetCashierByID(c.Context(), cashierID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Get User By ID failed", "error", err)
|
h.mongoLoggerSvc.Error("Get User By ID failed",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
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)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "cashierID", user.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
}
|
}
|
||||||
|
|
@ -316,24 +390,42 @@ type updateCashierReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
||||||
cashierIdStr := c.Params("id")
|
cashierIdStr := c.Params("id")
|
||||||
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
|
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("UpdateCashier failed", "error", err)
|
h.mongoLoggerSvc.Info("UpdateCashier invalid cashier ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
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
|
var req updateCashierReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("UpdateCashier failed", "error", err)
|
h.mongoLoggerSvc.Info("UpdateCashier failed to parse request body",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
|
|
||||||
if !ok {
|
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{
|
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
|
||||||
|
|
@ -353,8 +445,14 @@ func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("UpdateCashier failed", "error", err)
|
h.mongoLoggerSvc.Error("failed to update cashier",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update cashier", nil, nil)
|
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)
|
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
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
// CreateCompany godoc
|
||||||
// @Summary Create a company
|
// @Summary Create a company
|
||||||
// @Description Creates a company
|
// @Description Creates a company
|
||||||
// @Tags company
|
// @Tags company
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param createCompany body CreateCompanyReq true "Creates company"
|
// @Param createCompany body domain.CreateCompanyReq true "Creates company"
|
||||||
// @Success 200 {object} CompanyRes
|
// @Success 200 {object} domain.CompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /company [post]
|
// @Router /api/v1/company [post]
|
||||||
func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
||||||
var req CreateCompanyReq
|
var req domain.CreateCompanyReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
h.mongoLoggerSvc.Info("CreateCompanyReq failed",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), req.AdminID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Error fetching user", "error", err)
|
h.mongoLoggerSvc.Error("Error fetching user",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get user", err, nil)
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Time("timestamp", time.Now()),
|
||||||
|
)
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Company Wallet
|
// Create Company Wallet
|
||||||
|
|
@ -98,8 +66,13 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Create Company Wallet failed", "error", err)
|
h.mongoLoggerSvc.Error("Create Company Wallet failed",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create company wallet", err, nil)
|
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{
|
company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{
|
||||||
|
|
@ -109,20 +82,29 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
h.mongoLoggerSvc.Error("CreateCompanyReq failed to create company",
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
zap.Int64("userID", user.ID),
|
||||||
"error": "Internal server error",
|
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)
|
err = h.userSvc.UpdateUserCompany(c.Context(), user.ID, company.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CreateCompanyReq failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to update user company",
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
zap.Int64("userID", user.ID),
|
||||||
"error": "Internal server error",
|
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)
|
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -133,10 +115,10 @@ func (h *Handler) CreateCompany(c *fiber.Ctx) error {
|
||||||
// @Tags company
|
// @Tags company
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} CompanyRes
|
// @Success 200 {array} domain.GetCompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /company [get]
|
// @Router /api/v1/company [get]
|
||||||
func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
||||||
searchQuery := c.Query("query")
|
searchQuery := c.Query("query")
|
||||||
searchString := domain.ValidString{
|
searchString := domain.ValidString{
|
||||||
|
|
@ -149,8 +131,13 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -163,8 +150,13 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -178,14 +170,18 @@ func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
|
||||||
CreatedAfter: createdAfter,
|
CreatedAfter: createdAfter,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get companies", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get companies",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
|
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 {
|
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)
|
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
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "Company ID"
|
// @Param id path int true "Company ID"
|
||||||
// @Success 200 {object} CompanyRes
|
// @Success 200 {object} domain.GetCompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
companyID := c.Params("id")
|
companyID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
|
h.mongoLoggerSvc.Info("Invalid company ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
|
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)
|
company, err := h.companySvc.GetCompanyByID(c.Context(), id)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get company by ID", "companyID", id, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get company by ID",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
|
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)
|
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
|
// @Tags company
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} CompanyRes
|
// @Success 200 {object} domain.GetCompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error {
|
||||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
if !companyID.Valid {
|
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)
|
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get company by ID", "companyID", companyID.Value, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get company by ID",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
|
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)
|
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
|
// @Tags company
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} CompanyRes
|
// @Success 200 {array} domain.CompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) SearchCompany(c *fiber.Ctx) error {
|
||||||
searchQuery := c.Query("q")
|
searchQuery := c.Query("q")
|
||||||
if searchQuery == "" {
|
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)
|
companies, err := h.companySvc.SearchCompanyByName(c.Context(), searchQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get companies", "error", err)
|
h.mongoLoggerSvc.Info("Failed to get companies",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
|
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 {
|
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)
|
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
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "Company ID"
|
// @Param id path int true "Company ID"
|
||||||
// @Param updateCompany body UpdateCompanyReq true "Update Company"
|
// @Param updateCompany body domain.UpdateCompanyReq true "Update Company"
|
||||||
// @Success 200 {object} CompanyRes
|
// @Success 200 {object} domain.CompanyRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
|
||||||
|
|
||||||
companyID := c.Params("id")
|
companyID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
|
h.mongoLoggerSvc.Info("Invalid company ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
|
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 {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("UpdateCompanyReq failed", "error", err)
|
h.mongoLoggerSvc.Info("UpdateCompanyReq failed",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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{
|
company, err := h.companySvc.UpdateCompany(c.Context(), domain.ConvertUpdateCompanyReq(req))
|
||||||
ID: id,
|
|
||||||
Name: req.Name,
|
|
||||||
AdminID: req.AdminID,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to update company", "companyID", id, "error", err)
|
h.mongoLoggerSvc.Error("Failed to update company",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", err, nil)
|
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)
|
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
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) DeleteCompany(c *fiber.Ctx) error {
|
||||||
|
|
||||||
companyID := c.Params("id")
|
companyID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(companyID, 10, 64)
|
id, err := strconv.ParseInt(companyID, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid Company ID", "companyID", companyID, "error", err)
|
h.mongoLoggerSvc.Info("Invalid Company ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Company ID", err, nil)
|
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)
|
err = h.companySvc.DeleteCompany(c.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to delete by ID", "Company ID", id, "error", err)
|
h.mongoLoggerSvc.Info("Failed to delete by ID",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Company", err, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -8,9 +9,9 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type CustomersRes struct {
|
type CustomersRes struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
FirstName string `json:"first_name"`
|
FirstName string `json:"first_name"`
|
||||||
|
|
@ -26,6 +27,7 @@ type CustomersRes struct {
|
||||||
SuspendedAt time.Time `json:"suspended_at"`
|
SuspendedAt time.Time `json:"suspended_at"`
|
||||||
Suspended bool `json:"suspended"`
|
Suspended bool `json:"suspended"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllCustomers godoc
|
// GetAllCustomers godoc
|
||||||
// @Summary Get all Customers
|
// @Summary Get all Customers
|
||||||
// @Description Get all Customers
|
// @Description Get all Customers
|
||||||
|
|
@ -38,13 +40,18 @@ type CustomersRes struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /customer [get]
|
// @Router /api/v1/customer [get]
|
||||||
func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
// Checking to make sure that admin user has a company id in the token
|
// Checking to make sure that admin user has a company id in the token
|
||||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,8 +66,13 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -73,8 +85,13 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -99,12 +116,27 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
valErrs, ok := h.validator.Validate(c, filter)
|
valErrs, ok := h.validator.Validate(c, filter)
|
||||||
if !ok {
|
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)
|
customers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("GetAllCustomers failed", "error", err)
|
h.mongoLoggerSvc.Error("GetAllCustomers failed to get all users",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Customers", err, nil)
|
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))
|
var result []CustomersRes = make([]CustomersRes, len(customers))
|
||||||
|
|
@ -114,8 +146,14 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
if err == authentication.ErrRefreshTokenNotFound {
|
if err == authentication.ErrRefreshTokenNotFound {
|
||||||
lastLogin = &customer.CreatedAt
|
lastLogin = &customer.CreatedAt
|
||||||
} else {
|
} else {
|
||||||
h.logger.Error("Failed to get user last login", "userID", customer.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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{
|
result[index] = CustomersRes{
|
||||||
|
|
@ -150,7 +188,7 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
|
||||||
userIDstr := c.Params("id")
|
userIDstr := c.Params("id")
|
||||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
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)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -210,28 +259,47 @@ type updateCustomerReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req updateCustomerReq
|
var req updateCustomerReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
h.mongoLoggerSvc.Error("UpdateCustomers invalid request body",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
|
|
||||||
if !ok {
|
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")
|
CustomersIdStr := c.Params("id")
|
||||||
CustomersId, err := strconv.ParseInt(CustomersIdStr, 10, 64)
|
CustomersId, err := strconv.ParseInt(CustomersIdStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
h.mongoLoggerSvc.Info("Invalid Customers ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Customers ID", nil, nil)
|
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
|
// var companyID domain.ValidInt64
|
||||||
// role := c.Locals("role").(domain.Role)
|
// role := c.Locals("role").(domain.Role)
|
||||||
// if req.CompanyID != nil {
|
// if req.CompanyID != nil {
|
||||||
|
|
@ -262,8 +330,13 @@ func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("UpdateCustomers failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to update Customers",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Customers", nil, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Customers updated successfully", nil, nil)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,63 +8,9 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetALLPrematchOdds
|
|
||||||
// @Summary Retrieve all prematch odds
|
|
||||||
// @Description Retrieve all prematch odds from the database
|
|
||||||
// @Tags prematch
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200 {array} domain.Odd
|
|
||||||
// @Failure 500 {object} response.APIResponse
|
|
||||||
// @Router /odds [get]
|
|
||||||
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
|
|
||||||
|
|
||||||
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
|
|
||||||
if err != nil {
|
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRawOddsByMarketID
|
|
||||||
// @Summary Retrieve raw odds by Market ID
|
|
||||||
// @Description Retrieve raw odds records using a Market ID
|
|
||||||
// @Tags prematch
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param upcoming_id path string true "Upcoming ID"
|
|
||||||
// @Param market_id path string true "Market ID"
|
|
||||||
// @Success 200 {array} domain.RawOddsByMarketID
|
|
||||||
// @Failure 400 {object} response.APIResponse
|
|
||||||
// @Failure 500 {object} response.APIResponse
|
|
||||||
// @Router /odds/upcoming/{upcoming_id}/market/{market_id} [get]
|
|
||||||
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
|
|
||||||
|
|
||||||
marketID := c.Params("market_id")
|
|
||||||
upcomingID := c.Params("upcoming_id")
|
|
||||||
if marketID == "" {
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if upcomingID == "" {
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
|
|
||||||
if err != nil {
|
|
||||||
// fmt.Printf("Failed to fetch raw odds: %v market_id:%v upcomingID:%v\n", err, marketID, upcomingID)
|
|
||||||
h.logger.Error("Failed to get raw odds by market ID", "marketID", marketID, "upcomingID", upcomingID, "error", err)
|
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Retrieve all upcoming events
|
// @Summary Retrieve all upcoming events
|
||||||
// @Description Retrieve all upcoming events from the database
|
// @Description Retrieve all upcoming events from the database
|
||||||
// @Tags prematch
|
// @Tags prematch
|
||||||
|
|
@ -79,7 +25,7 @@ func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
|
||||||
// @Param last_start_time query string false "End Time"
|
// @Param last_start_time query string false "End Time"
|
||||||
// @Success 200 {array} domain.UpcomingEvent
|
// @Success 200 {array} domain.UpcomingEvent
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /events [get]
|
// @Router /api/v1/events [get]
|
||||||
func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
page := c.QueryInt("page", 1)
|
page := c.QueryInt("page", 1)
|
||||||
pageSize := c.QueryInt("page_size", 10)
|
pageSize := c.QueryInt("page_size", 10)
|
||||||
|
|
@ -97,8 +43,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
if leagueIDQuery != "" {
|
if leagueIDQuery != "" {
|
||||||
leagueIDInt, err := strconv.Atoi(leagueIDQuery)
|
leagueIDInt, err := strconv.Atoi(leagueIDQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid league id", "error", err)
|
h.mongoLoggerSvc.Error("invalid league id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
|
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{
|
leagueID = domain.ValidInt32{
|
||||||
Value: int32(leagueIDInt),
|
Value: int32(leagueIDInt),
|
||||||
|
|
@ -110,8 +61,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
if sportIDQuery != "" {
|
if sportIDQuery != "" {
|
||||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid sport id", "error", err)
|
h.mongoLoggerSvc.Info("invalid sport id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
|
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{
|
sportID = domain.ValidInt32{
|
||||||
Value: int32(sportIDint),
|
Value: int32(sportIDint),
|
||||||
|
|
@ -123,8 +79,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
if firstStartTimeQuery != "" {
|
if firstStartTimeQuery != "" {
|
||||||
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
firstStartTime = domain.ValidTime{
|
||||||
Value: firstStartTimeParsed,
|
Value: firstStartTimeParsed,
|
||||||
|
|
@ -137,8 +98,13 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
if lastStartTimeQuery != "" {
|
if lastStartTimeQuery != "" {
|
||||||
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
lastStartTime = domain.ValidTime{
|
||||||
Value: lastStartTimeParsed,
|
Value: lastStartTimeParsed,
|
||||||
|
|
@ -151,6 +117,26 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
Value: countryCodeQuery,
|
Value: countryCodeQuery,
|
||||||
Valid: countryCodeQuery != "",
|
Valid: countryCodeQuery != "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flaggedQuery := c.Query("flagged")
|
||||||
|
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(
|
events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(
|
||||||
c.Context(), domain.EventFilter{
|
c.Context(), domain.EventFilter{
|
||||||
SportID: sportID,
|
SportID: sportID,
|
||||||
|
|
@ -160,12 +146,17 @@ func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
CountryCode: countryCode,
|
CountryCode: countryCode,
|
||||||
|
Flagged: flagged,
|
||||||
})
|
})
|
||||||
|
|
||||||
// fmt.Printf("League ID: %v", leagueID)
|
// fmt.Printf("League ID: %v", leagueID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("getting error", "error", err)
|
h.mongoLoggerSvc.Error("Failed to retrieve all upcoming events",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
|
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))
|
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil, page, int(total))
|
||||||
|
|
@ -192,14 +183,18 @@ type TopLeague struct {
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {array} TopLeague
|
// @Success 200 {array} TopLeague
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /top-leagues [get]
|
// @Router /api/v1/top-leagues [get]
|
||||||
func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
||||||
|
|
||||||
leagues, err := h.leagueSvc.GetFeaturedLeagues(c.Context())
|
leagues, err := h.leagueSvc.GetFeaturedLeagues(c.Context())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Error while fetching top leagues", "err", err)
|
h.mongoLoggerSvc.Error("Error while fetching top leagues",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get featured leagues", nil, nil)
|
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))
|
var topLeague []TopLeague = make([]TopLeague, 0, len(leagues))
|
||||||
|
|
@ -212,8 +207,12 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error while fetching events for top league %v \n", league.ID)
|
h.mongoLoggerSvc.Warn("Error while fetching events for top league",
|
||||||
h.logger.Error("Error while fetching events for top league", "League ID", league.ID)
|
zap.Int64("LeagueID", league.ID),
|
||||||
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Time("timestamp", time.Now()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
topLeague = append(topLeague, TopLeague{
|
topLeague = append(topLeague, TopLeague{
|
||||||
LeagueID: league.ID,
|
LeagueID: league.ID,
|
||||||
|
|
@ -240,61 +239,34 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.UpcomingEvent
|
// @Success 200 {object} domain.UpcomingEvent
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetUpcomingEventByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
id := c.Params("id")
|
id := c.Params("id")
|
||||||
if 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)
|
event, err := h.eventSvc.GetUpcomingEventByID(c.Context(), id)
|
||||||
if err != nil {
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieve prematch odds by upcoming ID (FI)
|
|
||||||
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
|
|
||||||
// @Tags prematch
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param upcoming_id path string true "Upcoming Event ID (FI)"
|
|
||||||
// @Param limit query int false "Number of results to return (default: 10)"
|
|
||||||
// @Param offset query int false "Number of results to skip (default: 0)"
|
|
||||||
// @Success 200 {array} domain.Odd
|
|
||||||
// @Failure 400 {object} response.APIResponse
|
|
||||||
// @Failure 500 {object} response.APIResponse
|
|
||||||
// @Router /odds/upcoming/{upcoming_id} [get]
|
|
||||||
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
|
|
||||||
|
|
||||||
upcomingID := c.Params("upcoming_id")
|
|
||||||
if upcomingID == "" {
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
|
|
||||||
if err != nil || limit <= 0 {
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
|
|
||||||
if err != nil || offset < 0 {
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID)
|
|
||||||
if err != nil {
|
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateEventStatusReq struct {
|
type UpdateEventStatusReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,13 +280,78 @@ type UpdateEventStatusReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error {
|
||||||
eventID := c.Params("id")
|
eventID := c.Params("id")
|
||||||
err := h.eventSvc.UpdateEventStatus(c.Context(), eventID, domain.STATUS_REMOVED)
|
err := h.eventSvc.UpdateEventStatus(c.Context(), eventID, domain.STATUS_REMOVED)
|
||||||
|
|
||||||
if err != nil {
|
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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateEventFlaggedReq struct {
|
||||||
|
Flagged bool `json:"flagged" example:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEventFlagged godoc
|
||||||
|
// @Summary update the event flagged
|
||||||
|
// @Description Update the event flagged
|
||||||
|
// @Tags event
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param id path int true "Event ID"
|
||||||
|
// @Success 200 {object} response.APIResponse
|
||||||
|
// @Failure 400 {object} response.APIResponse
|
||||||
|
// @Failure 500 {object} response.APIResponse
|
||||||
|
// @Router /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())
|
||||||
|
}
|
||||||
|
|
||||||
|
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("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.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)
|
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
|
||||||
|
|
@ -2,9 +2,11 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateIssue godoc
|
// CreateIssue godoc
|
||||||
|
|
@ -19,42 +21,70 @@ import (
|
||||||
// @Failure 500 {object} domain.ErrorResponse
|
// @Failure 500 {object} domain.ErrorResponse
|
||||||
// @Router /api/v1/issues [post]
|
// @Router /api/v1/issues [post]
|
||||||
func (h *Handler) CreateIssue(c *fiber.Ctx) error {
|
func (h *Handler) CreateIssue(c *fiber.Ctx) error {
|
||||||
var req domain.ReportedIssue
|
role := c.Locals("role").(domain.Role)
|
||||||
|
userID := c.Locals("user_id").(int64)
|
||||||
|
|
||||||
|
var req domain.ReportedIssueReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
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)
|
created, err := h.issueReportingSvc.CreateReportedIssue(c.Context(), req, userID, role)
|
||||||
if err != nil {
|
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)
|
return c.Status(fiber.StatusCreated).JSON(created)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCustomerIssues godoc
|
// GetUserIssues godoc
|
||||||
// @Summary Get reported issues by a customer
|
// @Summary Get reported issues by a user
|
||||||
// @Description Returns all issues reported by a specific customer
|
// @Description Returns all issues reported by a specific user
|
||||||
// @Tags Issues
|
// @Tags Issues
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param customer_id path int true "Customer ID"
|
// @Param user_id path int true "User ID"
|
||||||
// @Param limit query int false "Limit"
|
// @Param limit query int false "Limit"
|
||||||
// @Param offset query int false "Offset"
|
// @Param offset query int false "Offset"
|
||||||
// @Success 200 {array} domain.ReportedIssue
|
// @Success 200 {array} domain.ReportedIssue
|
||||||
// @Failure 400 {object} domain.ErrorResponse
|
// @Failure 400 {object} domain.ErrorResponse
|
||||||
// @Failure 500 {object} domain.ErrorResponse
|
// @Failure 500 {object} domain.ErrorResponse
|
||||||
// @Router /api/v1/issues/customer/{customer_id} [get]
|
// @Router /api/v1/issues/user/{user_id} [get]
|
||||||
func (h *Handler) GetCustomerIssues(c *fiber.Ctx) error {
|
func (h *Handler) GetUserIssues(c *fiber.Ctx) error {
|
||||||
customerID, err := strconv.ParseInt(c.Params("customer_id"), 10, 64)
|
userID, err := strconv.ParseInt(c.Params("user_id"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid customer ID")
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
limit, offset := getPaginationParams(c)
|
limit, offset := getPaginationParams(c)
|
||||||
|
|
||||||
issues, err := h.issueReportingSvc.GetIssuesForCustomer(c.Context(), customerID, limit, offset)
|
issues, err := h.issueReportingSvc.GetIssuesForUser(c.Context(), userID, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
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)
|
return c.JSON(issues)
|
||||||
|
|
@ -75,7 +105,14 @@ func (h *Handler) GetAllIssues(c *fiber.Ctx) error {
|
||||||
|
|
||||||
issues, err := h.issueReportingSvc.GetAllIssues(c.Context(), limit, offset)
|
issues, err := h.issueReportingSvc.GetAllIssues(c.Context(), limit, offset)
|
||||||
if err != nil {
|
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)
|
return c.JSON(issues)
|
||||||
|
|
@ -101,11 +138,24 @@ func (h *Handler) UpdateIssueStatus(c *fiber.Ctx) error {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
if err := c.BodyParser(&body); err != nil || body.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 {
|
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 fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusNoContent)
|
return c.SendStatus(fiber.StatusNoContent)
|
||||||
|
|
@ -127,6 +177,12 @@ func (h *Handler) DeleteIssue(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.issueReportingSvc.DeleteIssue(c.Context(), issueID); err != nil {
|
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())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetAllLeagues godoc
|
// GetAllLeagues godoc
|
||||||
|
|
@ -18,7 +20,7 @@ import (
|
||||||
// @Success 200 {array} domain.League
|
// @Success 200 {array} domain.League
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /leagues [get]
|
// @Router /api/v1/leagues [get]
|
||||||
func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
||||||
page := c.QueryInt("page", 1)
|
page := c.QueryInt("page", 1)
|
||||||
pageSize := c.QueryInt("page_size", 10)
|
pageSize := c.QueryInt("page_size", 10)
|
||||||
|
|
@ -49,8 +51,13 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
||||||
if sportIDQuery != "" {
|
if sportIDQuery != "" {
|
||||||
sportIDint, err := strconv.Atoi(sportIDQuery)
|
sportIDint, err := strconv.Atoi(sportIDQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid sport id", "error", err)
|
h.mongoLoggerSvc.Info("invalid sport id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
|
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{
|
sportID = domain.ValidInt32{
|
||||||
Value: int32(sportIDint),
|
Value: int32(sportIDint),
|
||||||
|
|
@ -68,8 +75,12 @@ func (h *Handler) GetAllLeagues(c *fiber.Ctx) error {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error fetching league %v \n", err)
|
fmt.Printf("Error fetching league %v \n", err)
|
||||||
h.logger.Error("Failed to get leagues", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get all leagues",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get leagues", err, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "All leagues retrieved", leagues, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -78,59 +89,132 @@ type SetLeagueActiveReq struct {
|
||||||
IsActive bool `json:"is_active"`
|
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 {
|
func (h *Handler) SetLeagueActive(c *fiber.Ctx) error {
|
||||||
fmt.Printf("Set Active Leagues")
|
|
||||||
leagueIdStr := c.Params("id")
|
leagueIdStr := c.Params("id")
|
||||||
if leagueIdStr == "" {
|
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)
|
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||||
if err != nil {
|
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 SetLeagueActiveReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("SetLeagueReq failed", "error", err)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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 {
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) SetLeagueAsFeatured(c *fiber.Ctx) error {
|
type SetLeagueAsFeatured struct {
|
||||||
fmt.Printf("Set Active Leagues")
|
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")
|
leagueIdStr := c.Params("id")
|
||||||
if leagueIdStr == "" {
|
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)
|
leagueId, err := strconv.Atoi(leagueIdStr)
|
||||||
if err != nil {
|
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 {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("SetLeagueReq failed", "error", err)
|
h.logger.Error("SetLeagueFeaturedReq failed", "error", err)
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Failed to parse request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "League updated successfully", nil, nil)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -8,6 +9,7 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateManagerReq struct {
|
type CreateManagerReq struct {
|
||||||
|
|
@ -30,7 +32,7 @@ type CreateManagerReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /managers [post]
|
// @Router /api/v1/managers [post]
|
||||||
func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// Get user_id from middleware
|
// Get user_id from middleware
|
||||||
|
|
@ -38,11 +40,26 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||||
var req CreateManagerReq
|
var req CreateManagerReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("RegisterUser failed", "error", err)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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
|
var companyID domain.ValidInt64
|
||||||
|
|
@ -50,7 +67,11 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||||
if role == domain.RoleSuperAdmin {
|
if role == domain.RoleSuperAdmin {
|
||||||
if req.CompanyID == nil {
|
if req.CompanyID == nil {
|
||||||
h.logger.Error("RegisterUser failed error: company id is required")
|
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{
|
companyID = domain.ValidInt64{
|
||||||
Value: *req.CompanyID,
|
Value: *req.CompanyID,
|
||||||
|
|
@ -71,8 +92,12 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
_, err := h.userSvc.CreateUser(c.Context(), user, true)
|
_, err := h.userSvc.CreateUser(c.Context(), user, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CreateManager failed", "error", err)
|
h.mongoLoggerSvc.Error("CreateManager failed to create manager",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create manager", nil, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Manager created successfully", nil, nil)
|
||||||
|
|
||||||
|
|
@ -106,14 +131,19 @@ type ManagersRes struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /managers [get]
|
// @Router /api/v1/managers [get]
|
||||||
func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
// Checking to make sure that admin user has a company id in the token
|
// Checking to make sure that admin user has a company id in the token
|
||||||
if role != domain.RoleSuperAdmin && !companyId.Valid {
|
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")
|
searchQuery := c.Query("query")
|
||||||
|
|
@ -127,8 +157,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -141,8 +176,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -167,12 +207,28 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
valErrs, ok := h.validator.Validate(c, filter)
|
valErrs, ok := h.validator.Validate(c, filter)
|
||||||
if !ok {
|
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)
|
managers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("GetAllManagers failed", "error", err)
|
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))
|
var result []ManagersRes = make([]ManagersRes, len(managers))
|
||||||
|
|
@ -182,8 +238,13 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
if err == authentication.ErrRefreshTokenNotFound {
|
if err == authentication.ErrRefreshTokenNotFound {
|
||||||
lastLogin = &manager.CreatedAt
|
lastLogin = &manager.CreatedAt
|
||||||
} else {
|
} else {
|
||||||
h.logger.Error("Failed to get user last login", "userID", manager.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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{
|
result[index] = ManagersRes{
|
||||||
|
|
@ -218,7 +279,7 @@ func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyId := c.Locals("company_id").(domain.ValidInt64)
|
companyId := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
@ -226,11 +287,22 @@ func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// Only Super Admin / Admin / Branch Manager can view this route
|
// Only Super Admin / Admin / Branch Manager can view this route
|
||||||
if role != domain.RoleSuperAdmin && role != domain.RoleAdmin && role != domain.RoleBranchManager {
|
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 {
|
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")
|
userIDstr := c.Params("id")
|
||||||
|
|
@ -241,24 +313,47 @@ func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
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
|
// A Branch Manager can only fetch his own branch info
|
||||||
if role == domain.RoleBranchManager && user.ID != requestUserID {
|
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
|
// Check that only admin from company can view this route
|
||||||
if role != domain.RoleSuperAdmin && user.CompanyID.Value != companyId.Value {
|
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)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -301,13 +396,14 @@ type updateManagerReq struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateManagers(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req updateManagerReq
|
var req updateManagerReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("UpdateManagers failed", "error", err)
|
h.logger.Error("UpdateManagers failed", "error", err)
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/ws"
|
||||||
|
|
@ -14,6 +16,7 @@ import (
|
||||||
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/valyala/fasthttp/fasthttpadaptor"
|
"github.com/valyala/fasthttp/fasthttpadaptor"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func hijackHTTP(c *fiber.Ctx) (net.Conn, http.ResponseWriter, error) {
|
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 {
|
func (h *Handler) ConnectSocket(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("userID").(int64)
|
userID, ok := c.Locals("userID").(int64)
|
||||||
if !ok || userID == 0 {
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert *fiber.Ctx to *http.Request
|
// Convert *fiber.Ctx to *http.Request
|
||||||
req, err := adaptor.ConvertRequest(c, false)
|
req, err := adaptor.ConvertRequest(c, false)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to convert request")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a net.Conn hijacked from the fasthttp context
|
// Create a net.Conn hijacked from the fasthttp context
|
||||||
netConn, rw, err := hijackHTTP(c)
|
netConn, rw, err := hijackHTTP(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to hijack connection", "error", err)
|
h.mongoLoggerSvc.Error("Failed to hijack connection",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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
|
// Upgrade the connection using Gorilla's Upgrader
|
||||||
conn, err := ws.Upgrader.Upgrade(rw, req, nil)
|
conn, err := ws.Upgrader.Upgrade(rw, req, nil)
|
||||||
if err != 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()
|
netConn.Close()
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "WebSocket upgrade failed")
|
return fiber.NewError(fiber.StatusInternalServerError, "WebSocket upgrade failed:"+err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &ws.Client{
|
client := &ws.Client{
|
||||||
|
|
@ -88,9 +110,19 @@ func (h *Handler) ConnectSocket(c *fiber.Ctx) error {
|
||||||
_, _, err := conn.ReadMessage()
|
_, _, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
|
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 {
|
} 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
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -106,20 +138,34 @@ func (h *Handler) MarkNotificationAsRead(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req Request
|
var req Request
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "invalid user identification")
|
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)
|
fmt.Printf("Notification IDs: %v \n", req.NotificationIDs)
|
||||||
if err := h.notificationSvc.MarkAsRead(context.Background(), req.NotificationIDs, userID); err != nil {
|
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)
|
h.mongoLoggerSvc.Error("Failed to mark notifications as read",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update notification status")
|
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"})
|
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
|
var req Request
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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")
|
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 {
|
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)
|
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Failed to send single notification",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send 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})
|
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"message": "Single notification sent successfully", "notification_id": notification.ID})
|
||||||
|
|
||||||
case domain.NotificationDeliverySchemeBulk:
|
case domain.NotificationDeliverySchemeBulk:
|
||||||
|
|
@ -186,12 +245,16 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
||||||
Role: string(req.Reciever),
|
Role: string(req.Reciever),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("[NotificationSvc.CreateAndSendNotification] Failed to fetch recipients for bulk notification", "error", err)
|
h.mongoLoggerSvc.Error("[NotificationSvc.CreateAndSendNotification] Failed to fetch recipients for bulk notification",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch recipients")
|
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))
|
notificationIDs := make([]string, 0, len(recipients))
|
||||||
for _, user := range recipients {
|
for _, user := range recipients {
|
||||||
notification := &domain.Notification{
|
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 {
|
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
|
continue
|
||||||
}
|
}
|
||||||
notificationIDs = append(notificationIDs, notification.ID)
|
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{
|
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
|
||||||
"message": "Bulk notification sent successfully",
|
"message": "Bulk notification sent successfully",
|
||||||
"recipient_count": len(recipients),
|
"recipient_count": len(recipients),
|
||||||
|
|
@ -224,7 +297,11 @@ func (h *Handler) CreateAndSendNotification(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
default:
|
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")
|
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
|
// Convert limit and offset to integers
|
||||||
limit, err := strconv.Atoi(limitStr)
|
limit, err := strconv.Atoi(limitStr)
|
||||||
if err != nil || limit <= 0 {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
|
||||||
}
|
}
|
||||||
offset, err := strconv.Atoi(offsetStr)
|
offset, err := strconv.Atoi(offsetStr)
|
||||||
if err != nil || offset < 0 {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid offset value")
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid user ID in context")
|
h.mongoLoggerSvc.Error("[NotificationSvc.GetNotifications] Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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)
|
notifications, err := h.notificationSvc.ListNotifications(context.Background(), userID, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications", "error", err)
|
h.mongoLoggerSvc.Error("[NotificationSvc.GetNotifications] Failed to fetch notifications",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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{
|
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)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("[NotificationSvc.GetNotifications] Invalid user ID in context")
|
h.mongoLoggerSvc.Error("NotificationSvc.GetNotifications] Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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)
|
total, err := h.notificationSvc.CountUnreadNotifications(c.Context(), userID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("[NotificationSvc.CountUnreadNotifications] Failed to fetch unread notification count", "error", err)
|
h.mongoLoggerSvc.Error("[NotificationSvc.CountUnreadNotifications] Failed to fetch unread notification count",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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{
|
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
|
// Convert limit and offset to integers
|
||||||
limit, err := strconv.Atoi(limitStr)
|
limit, err := strconv.Atoi(limitStr)
|
||||||
if err != nil || limit <= 0 {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid limit value")
|
||||||
}
|
}
|
||||||
page, err := strconv.Atoi(pageStr)
|
page, err := strconv.Atoi(pageStr)
|
||||||
if err != nil || page <= 0 {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid page value")
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications, err := h.notificationSvc.GetAllNotifications(context.Background(), limit, ((page - 1) * limit))
|
notifications, err := h.notificationSvc.GetAllNotifications(context.Background(), limit, ((page - 1) * limit))
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch notifications")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
146
internal/web_server/handlers/odd_handler.go
Normal file
146
internal/web_server/handlers/odd_handler.go
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetALLPrematchOdds
|
||||||
|
// @Summary Retrieve all prematch odds
|
||||||
|
// @Description Retrieve all prematch odds from the database
|
||||||
|
// @Tags prematch
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {array} domain.Odd
|
||||||
|
// @Failure 500 {object} response.APIResponse
|
||||||
|
// @Router /api/v1/odds [get]
|
||||||
|
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
|
||||||
|
if err != 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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRawOddsByMarketID
|
||||||
|
// @Summary Retrieve raw odds by Market ID
|
||||||
|
// @Description Retrieve raw odds records using a Market ID
|
||||||
|
// @Tags prematch
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param upcoming_id path string true "Upcoming ID"
|
||||||
|
// @Param market_id path string true "Market ID"
|
||||||
|
// @Success 200 {array} domain.RawOddsByMarketID
|
||||||
|
// @Failure 400 {object} response.APIResponse
|
||||||
|
// @Failure 500 {object} response.APIResponse
|
||||||
|
// @Router /api/v1/odds/upcoming/{upcoming_id}/market/{market_id} [get]
|
||||||
|
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
marketID := c.Params("market_id")
|
||||||
|
if marketID == "" {
|
||||||
|
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 == "" {
|
||||||
|
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 {
|
||||||
|
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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Retrieve prematch odds by upcoming ID (FI)
|
||||||
|
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
|
||||||
|
// @Tags prematch
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param upcoming_id path string true "Upcoming Event ID (FI)"
|
||||||
|
// @Param limit query int false "Number of results to return (default: 10)"
|
||||||
|
// @Param offset query int false "Number of results to skip (default: 0)"
|
||||||
|
// @Success 200 {array} domain.Odd
|
||||||
|
// @Failure 400 {object} response.APIResponse
|
||||||
|
// @Failure 500 {object} response.APIResponse
|
||||||
|
// @Router /api/v1/odds/upcoming/{upcoming_id} [get]
|
||||||
|
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
upcomingID := c.Params("upcoming_id")
|
||||||
|
if upcomingID == "" {
|
||||||
|
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 {
|
||||||
|
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 {
|
||||||
|
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 {
|
||||||
|
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
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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 {
|
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")
|
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 {
|
func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
||||||
var req domain.ReferralSettingsReq
|
var req domain.ReferralSettingsReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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())
|
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create referral")
|
||||||
}
|
}
|
||||||
|
|
||||||
// only allow one referral setting for now
|
// only allow one referral setting for now
|
||||||
// for future it can be multiple and be able to choose from them
|
// for future it can be multiple and be able to choose from them
|
||||||
if settings != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "referral setting already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.referralSvc.CreateReferralSettings(c.Context(), req); err != nil {
|
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")
|
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 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @Router /referral/stats [get]
|
// @Router /api/v1/referral/stats [get]
|
||||||
func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := h.referralSvc.GetReferralStats(c.Context(), user.PhoneNumber)
|
stats, err := h.referralSvc.GetReferralStats(c.Context(), user.PhoneNumber)
|
||||||
if err != nil {
|
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")
|
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 403 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @Router /referral/settings [put]
|
// @Router /api/v1/referral/settings [put]
|
||||||
func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error {
|
func (h *Handler) UpdateReferralSettings(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get user", "userID", userID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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 {
|
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")
|
return fiber.NewError(fiber.StatusForbidden, "Admin access required")
|
||||||
}
|
}
|
||||||
|
|
||||||
var settings domain.ReferralSettings
|
var settings domain.ReferralSettings
|
||||||
if err := c.BodyParser(&settings); err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.UpdatedBy = user.PhoneNumber
|
settings.UpdatedBy = user.PhoneNumber
|
||||||
if err := h.referralSvc.UpdateReferralSettings(c.Context(), &settings); err != nil {
|
if err := h.referralSvc.UpdateReferralSettings(c.Context(), &settings); err != nil {
|
||||||
h.logger.Error("Failed to update referral settings", "error", err)
|
h.mongoLoggerSvc.Error("Failed to update referral settings",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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)
|
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 403 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @Router /referral/settings [get]
|
// @Router /api/v1/referral/settings [get]
|
||||||
func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
||||||
// userID, ok := c.Locals("user_id").(int64)
|
// userID, ok := c.Locals("user_id").(int64)
|
||||||
// if !ok || userID == 0 {
|
// if !ok || userID == 0 {
|
||||||
|
|
@ -153,18 +231,34 @@ func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
||||||
|
|
||||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Role != domain.RoleAdmin {
|
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")
|
return fiber.NewError(fiber.StatusForbidden, "Admin access required")
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get referral settings", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get referral settings",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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)
|
return response.WriteJSON(c, fiber.StatusOK, "Referral settings retrieved successfully", settings, nil)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultRes struct {
|
type ResultRes struct {
|
||||||
|
|
@ -24,17 +26,26 @@ type ResultRes struct {
|
||||||
// @Success 200 {array} ResultRes
|
// @Success 200 {array} ResultRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetResultsByEventID(c *fiber.Ctx) error {
|
||||||
eventID := c.Params("id")
|
eventID := c.Params("id")
|
||||||
if eventID == "" {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Event ID is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
results, outcomes, err := h.resultSvc.GetResultsForEvent(c.Context(), eventID)
|
results, outcomes, err := h.resultSvc.GetResultsForEvent(c.Context(), eventID)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve results")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateShopBet godoc
|
// CreateShopBet godoc
|
||||||
|
|
@ -21,7 +21,7 @@ import (
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
|
|
@ -30,20 +30,42 @@ func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req domain.ShopBetReq
|
var req domain.ShopBetReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CreateBetReq failed to parse request", "error", err)
|
h.mongoLoggerSvc.Info("CreateBetReq failed to parse request",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.logger.Error("CreateBetReq failed v", "error", valErrs)
|
var errMsg string
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
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)
|
shopBet, err := h.transactionSvc.CreateShopBet(c.Context(), userID, role, company_id, req)
|
||||||
|
|
||||||
if err != nil {
|
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)
|
res := domain.ConvertShopBet(shopBet)
|
||||||
|
|
||||||
|
|
@ -60,7 +82,7 @@ func (h *Handler) CreateShopBet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
betIDstr := c.Params("id")
|
betIDstr := c.Params("id")
|
||||||
|
|
@ -68,15 +90,25 @@ func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
||||||
betID, err := strconv.ParseInt(betIDstr, 10, 64)
|
betID, err := strconv.ParseInt(betIDstr, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CashoutReq failed bet id is invalid", "error", nil)
|
h.mongoLoggerSvc.Info("GetShopBetByBetID failed bet id is invalid",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "bet ID is invalid", nil, nil)
|
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)
|
bet, err := h.transactionSvc.GetShopBetByBetID(c.Context(), betID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CashoutReq failed invalid bet id", "error", err)
|
h.mongoLoggerSvc.Error("GetShopBetByBetID failed invalid bet id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid bet ID", err, nil)
|
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)
|
res := domain.ConvertShopBetDetail(bet)
|
||||||
|
|
@ -94,7 +126,7 @@ func (h *Handler) GetShopBetByBetID(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
betIDStr := c.Params("id")
|
betIDStr := c.Params("id")
|
||||||
|
|
@ -102,8 +134,13 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
||||||
betID, err := strconv.ParseInt(betIDStr, 10, 64)
|
betID, err := strconv.ParseInt(betIDStr, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CashoutReq invalid bet id", "error", err)
|
h.mongoLoggerSvc.Info("CashoutReq invalid bet id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid bet id", err, nil)
|
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)
|
userID := c.Locals("user_id").(int64)
|
||||||
|
|
@ -112,20 +149,41 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req domain.CashoutReq
|
var req domain.CashoutReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CashoutReq failed to parse request", "error", err)
|
h.mongoLoggerSvc.Info("CashoutReq failed to parse request",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.logger.Error("CashoutReq failed v", "error", valErrs)
|
var errMsg string
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
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)
|
transaction, err := h.transactionSvc.CashoutBet(c.Context(), betID, userID, role, req, companyID)
|
||||||
|
|
||||||
if err != nil {
|
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)
|
res := domain.ConvertShopTransaction(transaction)
|
||||||
|
|
||||||
|
|
@ -142,7 +200,7 @@ func (h *Handler) CashoutBet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
|
|
@ -151,27 +209,52 @@ func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req domain.CashoutReq
|
var req domain.CashoutReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CashoutReq failed to parse request", "error", err)
|
h.mongoLoggerSvc.Info("CashoutReq failed to parse request",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.logger.Error("CashoutReq failed v", "error", valErrs)
|
var errMsg string
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
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)
|
bet, err := h.transactionSvc.GetShopBetByCashoutID(c.Context(), req.CashoutID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CashoutReq failed invalid cashout id", "error", err)
|
h.mongoLoggerSvc.Info("CashoutReq failed invalid cashout id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil)
|
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)
|
transaction, err := h.transactionSvc.CashoutBet(c.Context(), bet.BetID, userID, role, req, companyID)
|
||||||
|
|
||||||
if err != nil {
|
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)
|
res := domain.ConvertShopTransaction(transaction)
|
||||||
|
|
||||||
|
|
@ -188,21 +271,30 @@ func (h *Handler) CashoutByCashoutID(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetShopBetByCashoutID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
cashoutID := c.Params("id")
|
cashoutID := c.Params("id")
|
||||||
|
|
||||||
if cashoutID == "" {
|
if cashoutID == "" {
|
||||||
h.logger.Error("CashoutReq failed cashout id is required", "error", nil)
|
h.mongoLoggerSvc.Info("CashoutReq failed cashout id is required",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "cashout ID is required", nil, nil)
|
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)
|
bet, err := h.transactionSvc.GetShopBetByCashoutID(c.Context(), cashoutID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("CashoutReq failed invalid cashout id", "error", err)
|
h.mongoLoggerSvc.Info("CashoutReq failed invalid cashout id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil)
|
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)
|
res := domain.ConvertShopBetDetail(bet)
|
||||||
|
|
@ -217,10 +309,10 @@ func (h *Handler) GetShopBetByCashoutID(c *fiber.Ctx) error {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param transferToWallet body domain.ShopDepositReq true "ShopDepositReq"
|
// @Param transferToWallet body domain.ShopDepositReq true "ShopDepositReq"
|
||||||
// @Success 200 {object} TransferWalletRes
|
// @Success 200 {object} domain.ShopDepositRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// Get sender ID from the cashier
|
// Get sender ID from the cashier
|
||||||
|
|
@ -230,7 +322,12 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
||||||
var req domain.ShopDepositReq
|
var req domain.ShopDepositReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,14 +337,26 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
||||||
for field, msg := range valErrs {
|
for field, msg := range valErrs {
|
||||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
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)
|
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
deposit, err := h.transactionSvc.CreateShopDeposit(c.Context(), userID, role, req)
|
deposit, err := h.transactionSvc.CreateShopDeposit(c.Context(), userID, role, req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Shop Deposit Error %v \n", err)
|
h.mongoLoggerSvc.Info("failed to create shop deposit",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
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)
|
res := domain.ConvertShopDeposit(deposit)
|
||||||
|
|
@ -265,7 +374,7 @@ func (h *Handler) DepositForCustomer(c *fiber.Ctx) error {
|
||||||
// @Success 200 {array} domain.ShopTransactionRes
|
// @Success 200 {array} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||||
// Get user_id from middleware
|
// Get user_id from middleware
|
||||||
// userID := c.Locals("user_id").(int64)
|
// userID := c.Locals("user_id").(int64)
|
||||||
|
|
@ -284,8 +393,13 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||||
if createdBeforeQuery != "" {
|
if createdBeforeQuery != "" {
|
||||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdBefore = domain.ValidTime{
|
||||||
Value: createdBeforeParsed,
|
Value: createdBeforeParsed,
|
||||||
|
|
@ -298,8 +412,13 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||||
if createdAfterQuery != "" {
|
if createdAfterQuery != "" {
|
||||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("invalid start_time format", "error", err)
|
h.mongoLoggerSvc.Info("invalid start_time format",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
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{
|
createdAfter = domain.ValidTime{
|
||||||
Value: createdAfterParsed,
|
Value: createdAfterParsed,
|
||||||
|
|
@ -317,8 +436,12 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get transactions", "error", err)
|
h.mongoLoggerSvc.Info("Failed to get transactions",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transactions", err, nil)
|
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))
|
res := make([]domain.ShopTransactionRes, len(transactions))
|
||||||
|
|
@ -340,18 +463,28 @@ func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
||||||
transactionID := c.Params("id")
|
transactionID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction, err := h.transactionSvc.GetShopTransactionByID(c.Context(), id)
|
transaction, err := h.transactionSvc.GetShopTransactionByID(c.Context(), id)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve transaction")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,28 +502,34 @@ func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.ShopTransactionRes
|
// @Success 200 {object} domain.ShopTransactionRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetShopBetByTransactionID(c *fiber.Ctx) error {
|
||||||
transactionID := c.Params("id")
|
transactionID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid transaction ID", "transactionID", transactionID, "error", err)
|
h.mongoLoggerSvc.Info("Invalid transaction ID",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "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)
|
transaction, err := h.transactionSvc.GetShopBetByShopTransactionID(c.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get transaction by ID", "transactionID", id, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get transaction by ID",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve transaction")
|
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)
|
res := domain.ConvertShopBetDetail(transaction)
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Shop bet retrieved successfully", res, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "Shop bet retrieved successfully", res, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateTransactionVerifiedReq struct {
|
|
||||||
Verified bool `json:"verified" example:"true"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateTransactionVerified godoc
|
// UpdateTransactionVerified godoc
|
||||||
// @Summary Updates the verified field of a transaction
|
// @Summary Updates the verified field of a transaction
|
||||||
// @Description Updates the verified status of a transaction
|
// @Description Updates the verified status of a transaction
|
||||||
|
|
@ -398,11 +537,11 @@ type UpdateTransactionVerifiedReq struct {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path int true "Transaction ID"
|
// @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
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
||||||
transactionID := c.Params("id")
|
transactionID := c.Params("id")
|
||||||
userID := c.Locals("user_id").(int64)
|
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)
|
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
var req UpdateTransactionVerifiedReq
|
var req domain.UpdateTransactionVerifiedReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse UpdateTransactionVerified request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse UpdateTransactionVerified request",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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 {
|
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)
|
err = h.transactionSvc.UpdateShopTransactionVerified(c.Context(), id, req.Verified, userID, role, companyID, branchID)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transaction verification")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateTicket godoc
|
// CreateTicket godoc
|
||||||
|
|
@ -19,29 +22,51 @@ import (
|
||||||
// @Success 200 {object} domain.CreateTicketRes
|
// @Success 200 {object} domain.CreateTicketRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /ticket [post]
|
// @Router /api/v1/ticket [post]
|
||||||
func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
||||||
var req domain.CreateTicketReq
|
var req domain.CreateTicketReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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())
|
newTicket, rows, err := h.ticketSvc.CreateTicket(c.Context(), req, c.IP())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
|
||||||
case ticket.ErrEventHasBeenRemoved, ticket.ErrTicketHasExpired,
|
var statusCode int
|
||||||
ticket.ErrRawOddInvalid, ticket.ErrTooManyOutcomesForTicket,
|
|
||||||
ticket.ErrTicketAmountTooHigh, ticket.ErrTicketLimitForSingleUser,
|
if isTicketError := h.ticketSvc.CheckTicketError(err); isTicketError {
|
||||||
ticket.ErrTicketWinningTooHigh:
|
statusCode = fiber.StatusBadRequest
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
} 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{
|
res := domain.CreateTicketRes{
|
||||||
FastCode: newTicket.ID,
|
FastCode: newTicket.ID,
|
||||||
|
|
@ -61,18 +86,28 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} domain.TicketRes
|
// @Success 200 {object} domain.TicketRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
|
||||||
ticketID := c.Params("id")
|
ticketID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(ticketID, 10, 64)
|
id, err := strconv.ParseInt(ticketID, 10, 64)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid ticket ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket, err := h.ticketSvc.GetTicketByID(c.Context(), id)
|
ticket, err := h.ticketSvc.GetTicketByID(c.Context(), id)
|
||||||
if err != nil {
|
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")
|
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
|
// @Success 200 {array} domain.TicketRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /ticket [get]
|
// @Router /api/v1/ticket [get]
|
||||||
func (h *Handler) GetAllTickets(c *fiber.Ctx) error {
|
func (h *Handler) GetAllTickets(c *fiber.Ctx) error {
|
||||||
|
|
||||||
tickets, err := h.ticketSvc.GetAllTickets(c.Context())
|
tickets, err := h.ticketSvc.GetAllTickets(c.Context())
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve tickets")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ type CreateRefillReq struct {
|
||||||
// @Success 200 {object} TransferWalletRes
|
// @Success 200 {object} TransferWalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
walletID := c.Params("id")
|
walletID := c.Params("id")
|
||||||
|
|
@ -135,14 +135,24 @@ func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
||||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
|
h.mongoLoggerSvc.Error("Invalid wallet ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
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))
|
transfers, err := h.walletSvc.GetTransfersByWallet(c.Context(), int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get transfers by wallet", "walletID", walletID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get transfers by wallet",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transfers", err, nil)
|
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
|
var transferResponses []TransferWalletRes
|
||||||
|
|
@ -164,7 +174,7 @@ func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} TransferWalletRes
|
// @Success 200 {object} TransferWalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
receiverIDString := c.Params("id")
|
receiverIDString := c.Params("id")
|
||||||
|
|
@ -172,59 +182,100 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
||||||
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
|
h.mongoLoggerSvc.Info("Invalid wallet ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
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
|
// Get sender ID from the cashier
|
||||||
userID := c.Locals("user_id").(int64)
|
userID := c.Locals("user_id").(int64)
|
||||||
role := c.Locals("role").(domain.Role)
|
role := c.Locals("role").(domain.Role)
|
||||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
fmt.Printf("\n\nCompany ID: %v\n\n", companyID.Value)
|
// fmt.Printf("\n\nCompany ID: %v\n\n", companyID.Value)
|
||||||
|
|
||||||
var senderID int64
|
var senderID int64
|
||||||
//TODO: check to make sure that the cashiers aren't transferring TO branch wallet
|
//TODO: check to make sure that the cashiers aren't transferring TO branch wallet
|
||||||
switch role {
|
switch role {
|
||||||
case domain.RoleCustomer:
|
case domain.RoleCustomer:
|
||||||
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
|
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
|
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:
|
case domain.RoleAdmin:
|
||||||
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
h.mongoLoggerSvc.Error("Failed to fetch company",
|
||||||
Message: "Failed to fetch company",
|
zap.Int64("userID", userID),
|
||||||
Error: err.Error(),
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||||
})
|
zap.Error(err),
|
||||||
// return response.WriteJSON(c, fiber.StatusInternalServerError, "Error fetching company", err, nil)
|
zap.Time("timestamp", time.Now()),
|
||||||
|
)
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
senderID = company.WalletID
|
senderID = company.WalletID
|
||||||
h.logger.Error("Will", "userID", userID, "role", role)
|
// h.logger.Error("Will", "userID", userID, "role", role)
|
||||||
|
|
||||||
case domain.RoleSuperAdmin:
|
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:
|
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:
|
case domain.RoleCashier:
|
||||||
cashierBranch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
|
cashierBranch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get branch", "user ID", userID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get branch by cashier",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve cashier branch", err, nil)
|
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
|
senderID = cashierBranch.WalletID
|
||||||
default:
|
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
|
var req CreateTransferReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CreateTransferReq failed", "error", err)
|
h.mongoLoggerSvc.Error("CreateTransferReq failed to parse body",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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(),
|
transfer, err := h.walletSvc.TransferToWallet(c.Context(),
|
||||||
|
|
@ -234,8 +285,13 @@ func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.mongoLoggerSvc.Error("Failed to transfer money to wallet", zap.Error(err))
|
h.mongoLoggerSvc.Error("Failed to transfer money to wallet",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Transfer Failed", err, nil)
|
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)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// RefillWallet godoc
|
// RefillWallet godoc
|
||||||
// @Summary Refill wallet
|
// @Summary Refill wallet
|
||||||
// @Description Super Admin route to refill a 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
|
// @Success 200 {object} TransferWalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) RefillWallet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
receiverIDString := c.Params("id")
|
receiverIDString := c.Params("id")
|
||||||
|
|
@ -263,21 +318,42 @@ func (h *Handler) RefillWallet(c *fiber.Ctx) error {
|
||||||
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
|
h.mongoLoggerSvc.Error("Invalid wallet ID",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
|
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
|
// Get sender ID from the cashier
|
||||||
|
|
||||||
var req CreateRefillReq
|
var req CreateRefillReq
|
||||||
|
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("CreateRefillReq failed", "error", err)
|
h.mongoLoggerSvc.Info("CreateRefillReq failed to parse CreateRefillReq",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
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)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
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(
|
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))
|
}, domain.TRANSFER_BANK, domain.PaymentDetails{}, fmt.Sprintf("Added %v to wallet directly by super-admin", req.Amount))
|
||||||
|
|
||||||
if !ok {
|
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)
|
res := convertTransfer(transfer)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CheckPhoneEmailExistReq struct {
|
type CheckPhoneEmailExistReq struct {
|
||||||
|
|
@ -32,23 +33,36 @@ type CheckPhoneEmailExistRes struct {
|
||||||
// @Success 200 {object} CheckPhoneEmailExistRes
|
// @Success 200 {object} CheckPhoneEmailExistRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req CheckPhoneEmailExistReq
|
var req CheckPhoneEmailExistReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse CheckPhoneEmailExist request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse CheckPhoneEmailExist request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "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())
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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)
|
emailExist, phoneExist, err := h.userSvc.CheckPhoneEmailExist(c.Context(), req.PhoneNumber, req.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to check phone/email existence", "error", err)
|
h.mongoLoggerSvc.Error("Failed to check phone/email existence",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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{
|
res := CheckPhoneEmailExistRes{
|
||||||
|
|
@ -73,17 +87,25 @@ type RegisterCodeReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req RegisterCodeReq
|
var req RegisterCodeReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse SendRegisterCode request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse SendRegisterCode request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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
|
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 {
|
if err := h.userSvc.SendRegisterCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||||
h.logger.Error("Failed to send register code", "error", err)
|
h.mongoLoggerSvc.Error("Failed to send register code",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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)
|
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||||
|
|
@ -126,17 +154,25 @@ type RegisterUserReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req RegisterUserReq
|
var req RegisterUserReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse RegisterUser request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse RegisterUser request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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{
|
user := domain.RegisterUserReq{
|
||||||
FirstName: req.FirstName,
|
FirstName: req.FirstName,
|
||||||
|
|
@ -150,7 +186,13 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
medium, err := getMedium(req.Email, req.PhoneNumber)
|
medium, err := getMedium(req.Email, req.PhoneNumber)
|
||||||
if err != nil {
|
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())
|
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) {
|
if errors.Is(err, domain.ErrOtpNotFound) {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "User already exist")
|
return fiber.NewError(fiber.StatusBadRequest, "User already exist")
|
||||||
}
|
}
|
||||||
h.logger.Error("RegisterUser failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to register user",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Unknown Error")
|
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)
|
newWallet, err := h.walletSvc.CreateCustomerWallet(c.Context(), newUser.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to create wallet for user", "userID", newUser.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to create wallet for user",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet")
|
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 != "" {
|
if req.ReferalCode != "" {
|
||||||
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferalCode)
|
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferalCode)
|
||||||
if err != nil {
|
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")
|
"Added 100.0 to wallet only as test for deployment")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to update wallet for user", "userID", newUser.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to update wallet for user",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user wallet")
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Registration successful", nil, nil)
|
||||||
|
|
@ -216,17 +279,25 @@ type ResetCodeReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req ResetCodeReq
|
var req ResetCodeReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse SendResetCode request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse SendResetCode request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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
|
var sentTo string
|
||||||
|
|
@ -238,13 +309,24 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
||||||
sentTo = req.PhoneNumber
|
sentTo = req.PhoneNumber
|
||||||
medium = domain.OtpMediumSms
|
medium = domain.OtpMediumSms
|
||||||
} else {
|
} 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")
|
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||||
h.logger.Error("Failed to send reset code", "error", err)
|
h.mongoLoggerSvc.Error("Failed to send reset code",
|
||||||
fmt.Println(err)
|
zap.String("medium", string(medium)),
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code")
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||||
|
|
@ -267,22 +349,36 @@ type ResetPasswordReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
||||||
|
|
||||||
var req ResetPasswordReq
|
var req ResetPasswordReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse ResetPassword request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse ResetPassword request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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)
|
medium, err := getMedium(req.Email, req.PhoneNumber)
|
||||||
if err != nil {
|
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())
|
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 {
|
if err := h.userSvc.ResetPassword(c.Context(), resetReq); err != nil {
|
||||||
h.logger.Error("Failed to reset password", "error", err)
|
h.mongoLoggerSvc.Error("Failed to reset password",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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)
|
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
|
||||||
|
|
@ -328,26 +429,40 @@ type UserProfileRes struct {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @Router /user/profile [get]
|
// @Router /api/v1/user/profile [get]
|
||||||
func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
||||||
|
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get user profile", "userID", userID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user profile",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "userID", userID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -396,37 +511,51 @@ type SearchUserByNameOrPhoneReq struct {
|
||||||
// @Success 200 {object} UserProfileRes
|
// @Success 200 {object} UserProfileRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
||||||
// TODO: Add filtering by role based on which user is calling this
|
// TODO: Add filtering by role based on which user is calling this
|
||||||
var req SearchUserByNameOrPhoneReq
|
var req SearchUserByNameOrPhoneReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to Search UserBy Name Or Phone failed",
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
zap.Any("request", req),
|
||||||
"error": "Invalid 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())
|
||||||
}
|
}
|
||||||
valErrs, ok := h.validator.Validate(c, req)
|
valErrs, ok := h.validator.Validate(c, req)
|
||||||
if !ok {
|
if !ok {
|
||||||
response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
var errMsg string
|
||||||
return nil
|
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)
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||||
|
|
||||||
users, err := h.userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString, req.Role, companyID)
|
users, err := h.userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString, req.Role, companyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user by name or phone",
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
zap.Any("request", req),
|
||||||
"error": "Internal server error",
|
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))
|
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -462,7 +591,7 @@ func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
||||||
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
||||||
// filter := user.Filter{
|
// filter := user.Filter{
|
||||||
|
|
@ -482,21 +611,36 @@ func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
||||||
userIDstr := c.Params("id")
|
userIDstr := c.Params("id")
|
||||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("failed to fetch user using UserID", "error", err)
|
h.mongoLoggerSvc.Info("failed to parse user id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
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)
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Get User By ID failed", "error", err)
|
h.mongoLoggerSvc.Error("Get User By ID failed",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
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)
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != authentication.ErrRefreshTokenNotFound {
|
if err != authentication.ErrRefreshTokenNotFound {
|
||||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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
|
lastLogin = &user.CreatedAt
|
||||||
|
|
@ -532,19 +676,29 @@ func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) DeleteUser(c *fiber.Ctx) error {
|
||||||
userIDstr := c.Params("id")
|
userIDstr := c.Params("id")
|
||||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("DeleteUser failed", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse user id",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", nil, nil)
|
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)
|
err = h.userSvc.DeleteUser(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to delete user", "userID", userID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to delete user",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to delete user", nil, nil)
|
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)
|
return response.WriteJSON(c, fiber.StatusOK, "User deleted successfully", nil, nil)
|
||||||
|
|
@ -569,14 +723,17 @@ type UpdateUserSuspendRes struct {
|
||||||
// @Success 200 {object} UpdateUserSuspendRes
|
// @Success 200 {object} UpdateUserSuspendRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
||||||
var req UpdateUserSuspendReq
|
var req UpdateUserSuspendReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
h.logger.Error("Failed to parse UpdateUserSuspend request", "error", err)
|
h.mongoLoggerSvc.Info("Failed to parse UpdateUserSuspend request",
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid 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())
|
||||||
}
|
}
|
||||||
fmt.Printf("user suspended %v \n", req)
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||||
var errMsg string
|
var errMsg string
|
||||||
for field, msg := range valErrs {
|
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)
|
err := h.userSvc.UpdateUserSuspend(c.Context(), req.UserID, req.Suspended)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to update user suspend status", "error", err)
|
h.mongoLoggerSvc.Error("Failed to update user suspend status",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "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{
|
res := UpdateUserSuspendRes{
|
||||||
|
|
@ -607,18 +769,27 @@ func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
||||||
// @Success 200 {array} domain.BetRes
|
// @Success 200 {array} domain.BetRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetBetByUserID(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
||||||
}
|
}
|
||||||
|
|
||||||
bets, err := h.betSvc.GetBetByUserID(c.Context(), userID)
|
bets, err := h.betSvc.GetBetByUserID(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get bets", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get bets",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve 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))
|
res := make([]domain.BetRes, len(bets))
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WalletRes struct {
|
type WalletRes struct {
|
||||||
|
|
@ -94,18 +96,28 @@ type BranchWalletRes struct {
|
||||||
// @Success 200 {object} WalletRes
|
// @Success 200 {object} WalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
|
||||||
walletID := c.Params("id")
|
walletID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet, err := h.walletSvc.GetWalletByID(c.Context(), id)
|
wallet, err := h.walletSvc.GetWalletByID(c.Context(), id)
|
||||||
if err != nil {
|
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")
|
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
|
// @Success 200 {array} WalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /wallet [get]
|
// @Router /api/v1/wallet [get]
|
||||||
func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
|
func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
|
||||||
|
|
||||||
wallets, err := h.walletSvc.GetAllWallets(c.Context())
|
wallets, err := h.walletSvc.GetAllWallets(c.Context())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get wallets", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get wallets",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
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))
|
var res []WalletRes = make([]WalletRes, 0, len(wallets))
|
||||||
|
|
@ -152,14 +168,18 @@ func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
|
||||||
// @Success 200 {array} WalletRes
|
// @Success 200 {array} WalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /branchWallet [get]
|
// @Router /api/v1/branchWallet [get]
|
||||||
func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
||||||
|
|
||||||
wallets, err := h.walletSvc.GetAllBranchWallets(c.Context())
|
wallets, err := h.walletSvc.GetAllBranchWallets(c.Context())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get wallets", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get wallets",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
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))
|
var res []BranchWalletRes = make([]BranchWalletRes, 0, len(wallets))
|
||||||
|
|
@ -191,14 +211,18 @@ func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
||||||
// @Success 200 {array} CustomerWalletRes
|
// @Success 200 {array} CustomerWalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /customerWallet [get]
|
// @Router /api/v1/customerWallet [get]
|
||||||
func (h *Handler) GetAllCustomerWallets(c *fiber.Ctx) error {
|
func (h *Handler) GetAllCustomerWallets(c *fiber.Ctx) error {
|
||||||
|
|
||||||
wallets, err := h.walletSvc.GetAllCustomerWallet(c.Context())
|
wallets, err := h.walletSvc.GetAllCustomerWallet(c.Context())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get wallets", "error", err)
|
h.mongoLoggerSvc.Error("Failed to get customer wallets",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
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))
|
var res []CustomerWalletRes = make([]CustomerWalletRes, 0, len(wallets))
|
||||||
|
|
@ -225,29 +249,53 @@ type UpdateWalletActiveReq struct {
|
||||||
// @Success 200 {object} response.APIResponse
|
// @Success 200 {object} response.APIResponse
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) UpdateWalletActive(c *fiber.Ctx) error {
|
||||||
|
|
||||||
walletID := c.Params("id")
|
walletID := c.Params("id")
|
||||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||||
if err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid wallet ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
var req UpdateWalletActiveReq
|
var req UpdateWalletActiveReq
|
||||||
if err := c.BodyParser(&req); err != nil {
|
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")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
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)
|
err = h.walletSvc.UpdateWalletActive(c.Context(), id, req.IsActive)
|
||||||
if err != nil {
|
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")
|
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
|
// @Success 200 {object} CustomerWalletRes
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {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 {
|
func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
|
||||||
|
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok || userID == 0 {
|
if !ok || userID == 0 {
|
||||||
h.logger.Error("Invalid user ID in context")
|
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
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)
|
role, ok := c.Locals("role").(domain.Role)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.logger.Error("Invalid role in context", "userID", userID)
|
h.mongoLoggerSvc.Error("Invalid role in context",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid role")
|
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 {
|
if role != domain.RoleCustomer {
|
||||||
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
|
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "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)
|
// 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)
|
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), userID)
|
||||||
if err != nil {
|
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")
|
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 400 {object} response.APIResponse
|
||||||
// @Failure 401 {object} response.APIResponse
|
// @Failure 401 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /cashierWallet [get]
|
// @Router /api/v1/cashierWallet [get]
|
||||||
func (h *Handler) GetWalletForCashier(c *fiber.Ctx) error {
|
func (h *Handler) GetWalletForCashier(c *fiber.Ctx) error {
|
||||||
cashierID, ok := c.Locals("user_id").(int64)
|
cashierID, ok := c.Locals("user_id").(int64)
|
||||||
|
|
||||||
if !ok || cashierID == 0 {
|
if !ok || cashierID == 0 {
|
||||||
h.logger.Error("Invalid cashier ID in context")
|
h.mongoLoggerSvc.Error("Invalid cashier ID in context",
|
||||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid cashier identification", nil, nil)
|
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)
|
role, ok := c.Locals("role").(domain.Role)
|
||||||
|
|
||||||
if !ok || role != domain.RoleCashier {
|
if !ok || role != domain.RoleCashier {
|
||||||
h.logger.Error("Unauthorized access", "cashierID", cashierID, "role", role)
|
h.mongoLoggerSvc.Error("Unauthorized access",
|
||||||
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
|
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)
|
branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
|
||||||
if !ok || !branchID.Valid {
|
if !ok || !branchID.Valid {
|
||||||
h.logger.Error("Invalid branch ID in context", "cashierID", cashierID)
|
h.mongoLoggerSvc.Info("Invalid branch ID in context",
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", nil, nil)
|
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)
|
branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get branch by ID", "branchID", branchID.Value, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get branch by ID",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch", err, nil)
|
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)
|
wallet, err := h.walletSvc.GetWalletByID(c.Context(), branch.WalletID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("Failed to get wallet for cashier", "cashierID", cashierID, "error", err)
|
h.mongoLoggerSvc.Error("Failed to get wallet for cashier",
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallet", err, nil)
|
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{
|
res := WalletRes{
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,38 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
|
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) authMiddleware(c *fiber.Ctx) error {
|
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")
|
authHeader := c.Get("Authorization")
|
||||||
if authHeader == "" {
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Authorization header missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
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")
|
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)
|
claim, err := jwtutil.ParseJwt(accessToken, a.JwtConfig.JwtAccessKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, jwtutil.ErrExpiredToken) {
|
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")
|
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")
|
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
|
// 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 {
|
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")
|
return fiber.NewError(fiber.StatusInternalServerError, "Company Role without Company ID")
|
||||||
}
|
}
|
||||||
c.Locals("user_id", claim.UserId)
|
c.Locals("user_id", claim.UserId)
|
||||||
|
|
@ -57,8 +88,13 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
||||||
if claim.Role == domain.RoleCashier {
|
if claim.Role == domain.RoleCashier {
|
||||||
branch, err := a.branchSvc.GetBranchByCashier(c.Context(), claim.UserId)
|
branch, err := a.branchSvc.GetBranchByCashier(c.Context(), claim.UserId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Error("Failed to get branch id for bet", "error", err)
|
a.mongoLoggerSvc.Error("Failed to get branch id for cashier",
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to branch id for bet")
|
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{
|
branchID = domain.ValidInt64{
|
||||||
Value: branch.ID,
|
Value: branch.ID,
|
||||||
|
|
@ -72,61 +108,116 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SuperAdminOnly(c *fiber.Ctx) error {
|
func (a *App) SuperAdminOnly(c *fiber.Ctx) error {
|
||||||
|
userID := c.Locals("user_id").(int64)
|
||||||
userRole := c.Locals("role").(domain.Role)
|
userRole := c.Locals("role").(domain.Role)
|
||||||
if userRole != domain.RoleSuperAdmin {
|
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()
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CompanyOnly(c *fiber.Ctx) error {
|
func (a *App) CompanyOnly(c *fiber.Ctx) error {
|
||||||
|
userID := c.Locals("user_id").(int64)
|
||||||
userRole := c.Locals("role").(domain.Role)
|
userRole := c.Locals("role").(domain.Role)
|
||||||
if userRole == domain.RoleCustomer {
|
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()
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) OnlyAdminAndAbove(c *fiber.Ctx) error {
|
func (a *App) OnlyAdminAndAbove(c *fiber.Ctx) error {
|
||||||
|
userID := c.Locals("user_id").(int64)
|
||||||
userRole := c.Locals("role").(domain.Role)
|
userRole := c.Locals("role").(domain.Role)
|
||||||
if userRole != domain.RoleSuperAdmin && userRole != domain.RoleAdmin {
|
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()
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) OnlyBranchManagerAndAbove(c *fiber.Ctx) error {
|
func (a *App) OnlyBranchManagerAndAbove(c *fiber.Ctx) error {
|
||||||
|
userID := c.Locals("user_id").(int64)
|
||||||
userRole := c.Locals("role").(domain.Role)
|
userRole := c.Locals("role").(domain.Role)
|
||||||
if userRole != domain.RoleSuperAdmin && userRole != domain.RoleAdmin && userRole != domain.RoleBranchManager {
|
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()
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) WebsocketAuthMiddleware(c *fiber.Ctx) error {
|
func (a *App) WebsocketAuthMiddleware(c *fiber.Ctx) error {
|
||||||
tokenStr := c.Query("token")
|
tokenStr := c.Query("token")
|
||||||
|
ip := c.IP()
|
||||||
|
userAgent := c.Get("User-Agent")
|
||||||
|
|
||||||
if tokenStr == "" {
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Missing token")
|
||||||
}
|
}
|
||||||
|
|
||||||
claim, err := jwtutil.ParseJwt(tokenStr, a.JwtConfig.JwtAccessKey)
|
claim, err := jwtutil.ParseJwt(tokenStr, a.JwtConfig.JwtAccessKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, jwtutil.ErrExpiredToken) {
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Token expired")
|
||||||
}
|
}
|
||||||
a.logger.Error("Invalid token", "error", err)
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid token")
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := claim.UserId
|
userID := claim.UserId
|
||||||
if userID == 0 {
|
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")
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Locals("userID", userID)
|
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()
|
return c.Next()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,20 +52,27 @@ func (a *App) initAppRoutes() {
|
||||||
a.mongoLoggerSvc,
|
a.mongoLoggerSvc,
|
||||||
)
|
)
|
||||||
|
|
||||||
group := a.fiber.Group("/api/v1")
|
|
||||||
|
|
||||||
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
||||||
return c.JSON(fiber.Map{
|
return c.JSON(fiber.Map{
|
||||||
"message": "Welcome to the FortuneBet API",
|
"message": "Welcome to the FortuneBet API",
|
||||||
"version": "1.0dev8.5",
|
"version": "1.0dev10",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
// Swagger
|
||||||
|
a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())
|
||||||
|
|
||||||
|
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.0dev10",
|
||||||
|
})
|
||||||
|
})
|
||||||
// Auth Routes
|
// Auth Routes
|
||||||
a.fiber.Post("/auth/login", h.LoginCustomer)
|
groupV1.Post("/auth/login", h.LoginCustomer)
|
||||||
a.fiber.Post("/auth/refresh", h.RefreshToken)
|
groupV1.Post("/auth/refresh", h.RefreshToken)
|
||||||
a.fiber.Post("/auth/logout", a.authMiddleware, h.LogOutCustomer)
|
groupV1.Post("/auth/logout", a.authMiddleware, h.LogOutCustomer)
|
||||||
a.fiber.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
|
groupV1.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("user_id").(int64)
|
userID, ok := c.Locals("user_id").(int64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
|
||||||
|
|
@ -92,148 +99,146 @@ func (a *App) initAppRoutes() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// User Routes
|
// User Routes
|
||||||
a.fiber.Post("/user/resetPassword", h.ResetPassword)
|
groupV1.Post("/user/resetPassword", h.ResetPassword)
|
||||||
a.fiber.Post("/user/sendResetCode", h.SendResetCode)
|
groupV1.Post("/user/sendResetCode", h.SendResetCode)
|
||||||
a.fiber.Post("/user/register", h.RegisterUser)
|
groupV1.Post("/user/register", h.RegisterUser)
|
||||||
a.fiber.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
groupV1.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
||||||
a.fiber.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
groupV1.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
||||||
a.fiber.Get("/user/profile", a.authMiddleware, h.UserProfile)
|
groupV1.Get("/user/profile", a.authMiddleware, h.UserProfile)
|
||||||
a.fiber.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
groupV1.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
||||||
a.fiber.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
|
groupV1.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
|
||||||
a.fiber.Post("/user/suspend", a.authMiddleware, h.UpdateUserSuspend)
|
groupV1.Post("/user/suspend", a.authMiddleware, h.UpdateUserSuspend)
|
||||||
a.fiber.Get("/user/ress", a.authMiddleware, h.GetBetByUserID)
|
groupV1.Get("/user/bets", a.authMiddleware, h.GetBetByUserID)
|
||||||
|
|
||||||
a.fiber.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
groupV1.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||||
a.fiber.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
groupV1.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||||
|
|
||||||
// Referral Routes
|
// Referral Routes
|
||||||
a.fiber.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
groupV1.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
||||||
a.fiber.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
groupV1.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
||||||
a.fiber.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
|
groupV1.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
|
||||||
a.fiber.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
|
groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
|
||||||
a.fiber.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
|
groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
|
||||||
|
|
||||||
// Bonus Routes
|
// Bonus Routes
|
||||||
a.fiber.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier)
|
groupV1.Get("/bonus", a.authMiddleware, h.GetBonusMultiplier)
|
||||||
a.fiber.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
|
groupV1.Post("/bonus/create", a.authMiddleware, h.CreateBonusMultiplier)
|
||||||
a.fiber.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
|
groupV1.Put("/bonus/update", a.authMiddleware, h.UpdateBonusMultiplier)
|
||||||
|
|
||||||
a.fiber.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
|
groupV1.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
|
||||||
a.fiber.Get("/cashiers/:id", a.authMiddleware, h.GetCashierByID)
|
groupV1.Get("/cashiers/:id", a.authMiddleware, h.GetCashierByID)
|
||||||
a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
groupV1.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
||||||
a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
groupV1.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
||||||
|
|
||||||
a.fiber.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
|
groupV1.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
|
||||||
a.fiber.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
|
groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
|
||||||
a.fiber.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
|
groupV1.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
|
||||||
|
|
||||||
a.fiber.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
groupV1.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
||||||
a.fiber.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
|
groupV1.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
|
||||||
a.fiber.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
groupV1.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
||||||
a.fiber.Put("/admin/:id", a.authMiddleware, h.UpdateAdmin)
|
groupV1.Put("/admin/:id", a.authMiddleware, h.UpdateAdmin)
|
||||||
|
|
||||||
a.fiber.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
groupV1.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
||||||
a.fiber.Get("/managers/:id", a.authMiddleware, h.GetManagerByID)
|
groupV1.Get("/managers/:id", a.authMiddleware, h.GetManagerByID)
|
||||||
a.fiber.Post("/managers", a.authMiddleware, h.CreateManager)
|
groupV1.Post("/managers", a.authMiddleware, h.CreateManager)
|
||||||
a.fiber.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
|
groupV1.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
|
||||||
a.fiber.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
|
groupV1.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
|
||||||
|
|
||||||
a.fiber.Get("/odds", h.GetALLPrematchOdds)
|
groupV1.Get("/odds", h.GetALLPrematchOdds)
|
||||||
a.fiber.Get("/odds/upcoming/:upcoming_id", h.GetOddsByUpcomingID)
|
groupV1.Get("/odds/upcoming/:upcoming_id", h.GetOddsByUpcomingID)
|
||||||
a.fiber.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
|
groupV1.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
|
||||||
|
|
||||||
a.fiber.Get("/events", h.GetAllUpcomingEvents)
|
groupV1.Get("/events", h.GetAllUpcomingEvents)
|
||||||
a.fiber.Get("/events/:id", h.GetUpcomingEventByID)
|
groupV1.Get("/events/:id", h.GetUpcomingEventByID)
|
||||||
a.fiber.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
|
groupV1.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
|
||||||
a.fiber.Get("/top-leagues", h.GetTopLeagues)
|
groupV1.Get("/top-leagues", h.GetTopLeagues)
|
||||||
|
groupV1.Get("/events/:id/flag", h.UpdateEventFlagged)
|
||||||
|
|
||||||
// Leagues
|
// Leagues
|
||||||
a.fiber.Get("/leagues", h.GetAllLeagues)
|
groupV1.Get("/leagues", h.GetAllLeagues)
|
||||||
a.fiber.Put("/leagues/:id/set-active", h.SetLeagueActive)
|
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
|
// Branch
|
||||||
a.fiber.Post("/branch", a.authMiddleware, h.CreateBranch)
|
groupV1.Post("/branch", a.authMiddleware, h.CreateBranch)
|
||||||
a.fiber.Get("/branch", a.authMiddleware, h.GetAllBranches)
|
groupV1.Get("/branch", a.authMiddleware, h.GetAllBranches)
|
||||||
a.fiber.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
|
groupV1.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
|
||||||
a.fiber.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
|
groupV1.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
|
||||||
a.fiber.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
|
groupV1.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
|
||||||
a.fiber.Put("/branch/:id/set-active", a.authMiddleware, h.UpdateBranchStatus)
|
groupV1.Put("/branch/:id/set-active", a.authMiddleware, h.UpdateBranchStatus)
|
||||||
a.fiber.Put("/branch/:id/set-inactive", a.authMiddleware, h.UpdateBranchStatus)
|
groupV1.Put("/branch/:id/set-inactive", a.authMiddleware, h.UpdateBranchStatus)
|
||||||
a.fiber.Delete("/branch/:id", a.authMiddleware, h.DeleteBranch)
|
groupV1.Delete("/branch/:id", a.authMiddleware, h.DeleteBranch)
|
||||||
a.fiber.Get("/search/branch", a.authMiddleware, h.SearchBranch)
|
groupV1.Get("/search/branch", a.authMiddleware, h.SearchBranch)
|
||||||
// /branch/search
|
// /branch/search
|
||||||
// branch/wallet
|
// branch/wallet
|
||||||
a.fiber.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers)
|
groupV1.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers)
|
||||||
a.fiber.Get("/branchCashier", a.authMiddleware, h.GetBranchForCashier)
|
groupV1.Get("/branchCashier", a.authMiddleware, h.GetBranchForCashier)
|
||||||
|
|
||||||
// Branch Operation
|
// Branch Operation
|
||||||
a.fiber.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
|
groupV1.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
|
||||||
a.fiber.Post("/supportedOperation", a.authMiddleware, h.CreateSupportedOperation)
|
groupV1.Post("/supportedOperation", a.authMiddleware, h.CreateSupportedOperation)
|
||||||
a.fiber.Post("/operation", a.authMiddleware, h.CreateBranchOperation)
|
groupV1.Post("/operation", a.authMiddleware, h.CreateBranchOperation)
|
||||||
a.fiber.Get("/branch/:id/operation", a.authMiddleware, h.GetBranchOperations)
|
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
|
// Company
|
||||||
a.fiber.Post("/company", a.authMiddleware, a.SuperAdminOnly, h.CreateCompany)
|
groupV1.Post("/company", a.authMiddleware, a.SuperAdminOnly, h.CreateCompany)
|
||||||
a.fiber.Get("/company", a.authMiddleware, a.SuperAdminOnly, h.GetAllCompanies)
|
groupV1.Get("/company", a.authMiddleware, a.SuperAdminOnly, h.GetAllCompanies)
|
||||||
a.fiber.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
|
groupV1.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
|
||||||
a.fiber.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
|
groupV1.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
|
||||||
a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
groupV1.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
||||||
a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
groupV1.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||||
a.fiber.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
groupV1.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
||||||
a.fiber.Get("/admin-company", a.authMiddleware, h.GetCompanyForAdmin)
|
groupV1.Get("/admin-company", a.authMiddleware, h.GetCompanyForAdmin)
|
||||||
|
|
||||||
// Ticket Routes
|
// Ticket Routes
|
||||||
a.fiber.Post("/ticket", h.CreateTicket)
|
groupV1.Post("/ticket", h.CreateTicket)
|
||||||
a.fiber.Get("/ticket", h.GetAllTickets)
|
groupV1.Get("/ticket", h.GetAllTickets)
|
||||||
a.fiber.Get("/ticket/:id", h.GetTicketByID)
|
groupV1.Get("/ticket/:id", h.GetTicketByID)
|
||||||
|
|
||||||
// Bet Routes
|
// Bet Routes
|
||||||
a.fiber.Post("/sport/bet", a.authMiddleware, h.CreateBet)
|
groupV1.Post("/sport/bet", a.authMiddleware, h.CreateBet)
|
||||||
a.fiber.Post("/sport/bet/fastcode", a.authMiddleware, h.CreateBetWithFastCode)
|
groupV1.Post("/sport/bet/fastcode", a.authMiddleware, h.CreateBetWithFastCode)
|
||||||
a.fiber.Get("/sport/bet", a.authMiddleware, h.GetAllBet)
|
groupV1.Get("/sport/bet", a.authMiddleware, h.GetAllBet)
|
||||||
a.fiber.Get("/sport/bet/:id", h.GetBetByID)
|
groupV1.Get("/sport/bet/:id", h.GetBetByID)
|
||||||
a.fiber.Get("/sport/bet/cashout/:id", a.authMiddleware, h.GetBetByCashoutID)
|
groupV1.Patch("/sport/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
||||||
a.fiber.Patch("/sport/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
groupV1.Delete("/sport/bet/:id", a.authMiddleware, h.DeleteBet)
|
||||||
a.fiber.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
|
// Wallet
|
||||||
a.fiber.Get("/wallet", h.GetAllWallets)
|
groupV1.Get("/wallet", h.GetAllWallets)
|
||||||
a.fiber.Get("/wallet/:id", h.GetWalletByID)
|
groupV1.Get("/wallet/:id", h.GetWalletByID)
|
||||||
a.fiber.Put("/wallet/:id", h.UpdateWalletActive)
|
groupV1.Put("/wallet/:id", h.UpdateWalletActive)
|
||||||
a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
|
groupV1.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
|
||||||
a.fiber.Get("/customerWallet", a.authMiddleware, h.GetAllCustomerWallets)
|
groupV1.Get("/customerWallet", a.authMiddleware, h.GetAllCustomerWallets)
|
||||||
a.fiber.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
|
groupV1.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
|
||||||
|
|
||||||
// Transfer
|
// Transfer
|
||||||
// /transfer/wallet - transfer from one wallet to another wallet
|
// /transfer/wallet - transfer from one wallet to another wallet
|
||||||
a.fiber.Post("/transfer/wallet/:id", a.authMiddleware, h.TransferToWallet)
|
groupV1.Post("/transfer/wallet/:id", a.authMiddleware, h.TransferToWallet)
|
||||||
a.fiber.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
|
groupV1.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
|
||||||
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
groupV1.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||||
|
|
||||||
//Chapa Routes
|
//Chapa Routes
|
||||||
group.Post("/chapa/payments/webhook/verify", h.WebhookCallback)
|
a.fiber.Post("/chapa/payments/webhook/verify", h.WebhookCallback)
|
||||||
group.Get("/chapa/payments/manual/verify/:tx_ref", h.ManualVerifyTransaction)
|
a.fiber.Get("/chapa/payments/manual/verify/:tx_ref", h.ManualVerifyTransaction)
|
||||||
group.Post("/chapa/payments/deposit", a.authMiddleware, h.InitiateDeposit)
|
a.fiber.Post("/chapa/payments/deposit", a.authMiddleware, h.InitiateDeposit)
|
||||||
group.Post("/chapa/payments/withdraw", a.authMiddleware, h.InitiateWithdrawal)
|
a.fiber.Post("/chapa/payments/withdraw", a.authMiddleware, h.InitiateWithdrawal)
|
||||||
group.Get("/chapa/banks", h.GetSupportedBanks)
|
a.fiber.Get("/chapa/banks", h.GetSupportedBanks)
|
||||||
|
|
||||||
// Currencies
|
// Currencies
|
||||||
group.Get("/currencies", h.GetSupportedCurrencies)
|
groupV1.Get("/currencies", h.GetSupportedCurrencies)
|
||||||
group.Get("/currencies/convert", h.ConvertCurrency)
|
groupV1.Get("/currencies/convert", h.ConvertCurrency)
|
||||||
|
|
||||||
//Report Routes
|
//Report Routes
|
||||||
group.Get("/reports/dashboard", h.GetDashboardReport)
|
groupV1.Get("/reports/dashboard", h.GetDashboardReport)
|
||||||
group.Get("/report-files/download/:filename", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportFile)
|
groupV1.Get("/report-files/download/:filename", a.authMiddleware, a.OnlyAdminAndAbove, h.DownloadReportFile)
|
||||||
group.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
groupV1.Get("/report-files/list", a.authMiddleware, a.OnlyAdminAndAbove, h.ListReportFiles)
|
||||||
|
|
||||||
//Wallet Monitor Service
|
//Wallet Monitor Service
|
||||||
// group.Get("/debug/wallet-monitor/status", func(c *fiber.Ctx) error {
|
// group.Get("/debug/wallet-monitor/status", func(c *fiber.Ctx) error {
|
||||||
|
|
@ -256,48 +261,48 @@ func (a *App) initAppRoutes() {
|
||||||
// group.Get("/chapa/transfers/verify/:transfer_ref", h.VerifyTransfer)
|
// group.Get("/chapa/transfers/verify/:transfer_ref", h.VerifyTransfer)
|
||||||
|
|
||||||
//Alea Play Virtual Game Routes
|
//Alea Play Virtual Game Routes
|
||||||
group.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
groupV1.Get("/alea-play/launch", a.authMiddleware, h.LaunchAleaGame)
|
||||||
group.Post("/webhooks/alea-play", a.authMiddleware, h.HandleAleaCallback)
|
groupV1.Post("/webhooks/alea-play", a.authMiddleware, h.HandleAleaCallback)
|
||||||
|
|
||||||
//Veli Virtual Game Routes
|
//Veli Virtual Game Routes
|
||||||
group.Post("/veli/providers", h.GetProviders)
|
groupV1.Post("/veli/providers", h.GetProviders)
|
||||||
group.Post("/veli/games-list", h.GetGamesByProvider)
|
groupV1.Post("/veli/games-list", h.GetGamesByProvider)
|
||||||
group.Post("/veli/start-game", a.authMiddleware, h.StartGame)
|
groupV1.Post("/veli/start-game", a.authMiddleware, h.StartGame)
|
||||||
group.Post("/veli/start-demo-game", a.authMiddleware, h.StartDemoGame)
|
groupV1.Post("/veli/start-demo-game", a.authMiddleware, h.StartDemoGame)
|
||||||
a.fiber.Post("/balance", h.GetBalance)
|
a.fiber.Post("/balance", h.GetBalance)
|
||||||
// a.fiber.Post("/bet", h.PlaceBet)
|
// a.fiber.Post("/bet", h.PlaceBet)
|
||||||
// a.fiber.Post("/win", h.RegisterWin)
|
// a.fiber.Post("/win", h.RegisterWin)
|
||||||
// a.fiber.Post("/cancel", h.CancelTransaction)
|
// a.fiber.Post("/cancel", h.CancelTransaction)
|
||||||
group.Post("/veli/gaming-activity", h.GetGamingActivity)
|
groupV1.Post("/veli/gaming-activity", h.GetGamingActivity)
|
||||||
|
|
||||||
//mongoDB logs
|
//mongoDB logs
|
||||||
ctx := context.Background()
|
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
|
// Recommendation Routes
|
||||||
// group.Get("/virtual-games/recommendations/:userID", h.GetRecommendations)
|
// group.Get("/virtual-games/recommendations/:userID", h.GetRecommendations)
|
||||||
|
|
||||||
// Transactions /shop/transactions
|
// Transactions /shop/transactions
|
||||||
a.fiber.Post("/shop/bet", a.authMiddleware, a.CompanyOnly, h.CreateShopBet)
|
groupV1.Post("/shop/bet", a.authMiddleware, a.CompanyOnly, h.CreateShopBet)
|
||||||
a.fiber.Get("/shop/bet/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByBetID)
|
groupV1.Get("/shop/bet/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByBetID)
|
||||||
a.fiber.Post("/shop/bet/:id/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
groupV1.Post("/shop/bet/:id/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||||
a.fiber.Post("/shop/bet/:id/generate", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
groupV1.Post("/shop/bet/:id/generate", a.authMiddleware, a.CompanyOnly, h.CashoutBet)
|
||||||
a.fiber.Get("/shop/cashout/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByCashoutID)
|
groupV1.Get("/shop/cashout/:id", a.authMiddleware, a.CompanyOnly, h.GetShopBetByCashoutID)
|
||||||
a.fiber.Post("/shop/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutByCashoutID)
|
groupV1.Post("/shop/cashout", a.authMiddleware, a.CompanyOnly, h.CashoutByCashoutID)
|
||||||
a.fiber.Post("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
groupV1.Post("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||||
// a.fiber.Get("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
// groupV1.Get("/shop/deposit", a.authMiddleware, a.CompanyOnly, h.DepositForCustomer)
|
||||||
a.fiber.Get("/shop/transaction", a.authMiddleware, h.GetAllTransactions)
|
groupV1.Get("/shop/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||||
a.fiber.Get("/shop/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
groupV1.Get("/shop/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
||||||
a.fiber.Get("/shop/transaction/:id/bet", a.authMiddleware, h.GetShopBetByTransactionID)
|
groupV1.Get("/shop/transaction/:id/bet", a.authMiddleware, h.GetShopBetByTransactionID)
|
||||||
a.fiber.Put("/shop/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
groupV1.Put("/shop/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||||
|
|
||||||
// Notification Routes
|
// Notification Routes
|
||||||
a.fiber.Get("/ws/connect", a.WebsocketAuthMiddleware, h.ConnectSocket)
|
groupV1.Get("/ws/connect", a.WebsocketAuthMiddleware, h.ConnectSocket)
|
||||||
a.fiber.Get("/notifications", a.authMiddleware, h.GetNotifications)
|
groupV1.Get("/notifications", a.authMiddleware, h.GetNotifications)
|
||||||
a.fiber.Get("/notifications/all", a.authMiddleware, h.GetAllNotifications)
|
groupV1.Get("/notifications/all", a.authMiddleware, h.GetAllNotifications)
|
||||||
a.fiber.Post("/notifications/mark-as-read", a.authMiddleware, h.MarkNotificationAsRead)
|
groupV1.Post("/notifications/mark-as-read", a.authMiddleware, h.MarkNotificationAsRead)
|
||||||
a.fiber.Get("/notifications/unread", a.authMiddleware, h.CountUnreadNotifications)
|
groupV1.Get("/notifications/unread", a.authMiddleware, h.CountUnreadNotifications)
|
||||||
a.fiber.Post("/notifications/create", a.authMiddleware, h.CreateAndSendNotification)
|
groupV1.Post("/notifications/create", a.authMiddleware, h.CreateAndSendNotification)
|
||||||
|
|
||||||
// Virtual Game Routes
|
// Virtual Game Routes
|
||||||
a.fiber.Post("/virtual-game/launch", a.authMiddleware, h.LaunchVirtualGame)
|
a.fiber.Post("/virtual-game/launch", a.authMiddleware, h.LaunchVirtualGame)
|
||||||
|
|
@ -310,21 +315,14 @@ func (a *App) initAppRoutes() {
|
||||||
a.fiber.Post("/tournamentWin ", h.HandleTournamentWin)
|
a.fiber.Post("/tournamentWin ", h.HandleTournamentWin)
|
||||||
a.fiber.Get("/popok/games", h.GetGameList)
|
a.fiber.Get("/popok/games", h.GetGameList)
|
||||||
a.fiber.Get("/popok/games/recommend", a.authMiddleware, h.RecommendGames)
|
a.fiber.Get("/popok/games/recommend", a.authMiddleware, h.RecommendGames)
|
||||||
group.Post("/virtual-game/favorites", a.authMiddleware, h.AddFavorite)
|
groupV1.Post("/virtual-game/favorites", a.authMiddleware, h.AddFavorite)
|
||||||
group.Delete("/virtual-game/favorites/:gameID", a.authMiddleware, h.RemoveFavorite)
|
groupV1.Delete("/virtual-game/favorites/:gameID", a.authMiddleware, h.RemoveFavorite)
|
||||||
group.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
|
groupV1.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
|
||||||
|
|
||||||
//Issue Reporting Routes
|
//Issue Reporting Routes
|
||||||
group.Post("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateIssue)
|
groupV1.Post("/issues", a.authMiddleware, h.CreateIssue) //anyone who has logged can report a
|
||||||
group.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetCustomerIssues)
|
groupV1.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
|
||||||
group.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
|
||||||
group.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
groupV1.Patch("/issues/:issue_id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
|
||||||
group.Delete("/issues/:issue_id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)
|
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]
|
|
||||||
|
|
|
||||||
5
makefile
5
makefile
|
|
@ -43,10 +43,11 @@ migrations/up:
|
||||||
postgres:
|
postgres:
|
||||||
@echo 'Running postgres db...'
|
@echo 'Running postgres db...'
|
||||||
docker compose -f docker-compose.yml exec postgres psql -U root -d gh
|
docker compose -f docker-compose.yml exec postgres psql -U root -d gh
|
||||||
.PHONY: backup
|
.PHONY: backup
|
||||||
backup:
|
backup:
|
||||||
@mkdir -p backup
|
@mkdir -p backup
|
||||||
@docker exec -t fortunebet-backend-postgres-1 pg_dumpall -c -U root | gzip > backup/dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.gz
|
@docker exec -t fortunebet-backend-postgres-1 pg_dumpall -c -U root | gzip > backup/dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.gz
|
||||||
|
|
||||||
restore:
|
restore:
|
||||||
@echo "Restoring latest backup..."
|
@echo "Restoring latest backup..."
|
||||||
@latest_file=$$(ls -t backup/dump_*.sql.gz | head -n 1); \
|
@latest_file=$$(ls -t backup/dump_*.sql.gz | head -n 1); \
|
||||||
|
|
@ -55,6 +56,8 @@ restore:
|
||||||
restore_file:
|
restore_file:
|
||||||
@echo "Restoring latest backup..."
|
@echo "Restoring latest backup..."
|
||||||
gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||||
|
seed_data:
|
||||||
|
cat db/data/seed_data.sql | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||||
postgres_log:
|
postgres_log:
|
||||||
docker logs fortunebet-backend-postgres-1
|
docker logs fortunebet-backend-postgres-1
|
||||||
.PHONY: swagger
|
.PHONY: swagger
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user