fixes while integrating
This commit is contained in:
parent
42788e6f9f
commit
910d592bef
343
db/data/001_initial_seed_data.sql
Normal file
343
db/data/001_initial_seed_data.sql
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
-- 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,', 'Alamata,'),
|
||||
('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;
|
||||
|
||||
-- Settings Initial Data
|
||||
INSERT INTO global_settings (key, value)
|
||||
VALUES ('sms_provider', 'afro_message'),
|
||||
('max_number_of_outcomes', '30'),
|
||||
('bet_amount_limit', '10000000'),
|
||||
('daily_ticket_limit', '50'),
|
||||
('total_winnings_limit', '1000000'),
|
||||
('amount_for_bet_referral', '1000000'),
|
||||
('cashback_amount_cap', '1000') ON CONFLICT (key) DO NOTHING;
|
||||
|
||||
-- Users
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'John',
|
||||
'Doe',
|
||||
'john.doe@example.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
),
|
||||
(
|
||||
2,
|
||||
'Test',
|
||||
'Admin',
|
||||
'test.admin@gmail.com',
|
||||
'0988554466',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
),
|
||||
(
|
||||
3,
|
||||
'Samuel',
|
||||
'Tariku',
|
||||
'cybersamt@gmail.com',
|
||||
'0911111111',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
4,
|
||||
'Kirubel',
|
||||
'Kibru',
|
||||
'kirubel.jkl679@gmail.com',
|
||||
'0911554486',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET first_name = EXCLUDED.first_name,
|
||||
last_name = EXCLUDED.last_name,
|
||||
email = EXCLUDED.email,
|
||||
phone_number = EXCLUDED.phone_number,
|
||||
password = EXCLUDED.password,
|
||||
role = EXCLUDED.role,
|
||||
email_verified = EXCLUDED.email_verified,
|
||||
phone_verified = EXCLUDED.phone_verified,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at,
|
||||
suspended = EXCLUDED.suspended,
|
||||
company_id = EXCLUDED.company_id;
|
||||
-- Supported Operations
|
||||
INSERT INTO supported_operations (id, name, description)
|
||||
VALUES (1, 'SportBook', 'Sportbook operations'),
|
||||
(2, 'Virtual', 'Virtual operations') ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET name = EXCLUDED.name,
|
||||
description = EXCLUDED.description;
|
||||
-- Wallets
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'regular_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
2,
|
||||
5000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'static_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
3,
|
||||
20000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'company_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
4,
|
||||
15000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'branch_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET balance = EXCLUDED.balance,
|
||||
is_withdraw = EXCLUDED.is_withdraw,
|
||||
is_bettable = EXCLUDED.is_bettable,
|
||||
is_transferable = EXCLUDED.is_transferable,
|
||||
user_id = EXCLUDED.user_id,
|
||||
type = EXCLUDED.type,
|
||||
currency = EXCLUDED.currency,
|
||||
is_active = EXCLUDED.is_active,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
-- Customer Wallets
|
||||
INSERT INTO customer_wallets (
|
||||
id,
|
||||
customer_id,
|
||||
regular_wallet_id,
|
||||
static_wallet_id
|
||||
)
|
||||
VALUES (1, 1, 1, 2) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET customer_id = EXCLUDED.customer_id,
|
||||
regular_wallet_id = EXCLUDED.regular_wallet_id,
|
||||
static_wallet_id = EXCLUDED.static_wallet_id;
|
||||
-- Company
|
||||
INSERT INTO companies (
|
||||
id,
|
||||
name,
|
||||
slug,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'FortuneBets',
|
||||
'fortunebets',
|
||||
2,
|
||||
3,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET name = EXCLUDED.name,
|
||||
slug = EXCLUDED.slug,
|
||||
admin_id = EXCLUDED.admin_id,
|
||||
wallet_id = EXCLUDED.wallet_id,
|
||||
deducted_percentage = EXCLUDED.deducted_percentage,
|
||||
is_active = EXCLUDED.is_active,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
-- Branch
|
||||
INSERT INTO branches (
|
||||
id,
|
||||
name,
|
||||
location,
|
||||
wallet_id,
|
||||
branch_manager_id,
|
||||
company_id,
|
||||
is_self_owned,
|
||||
profit_percent,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'Test Branch',
|
||||
'addis_ababa',
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
TRUE,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET name = EXCLUDED.name,
|
||||
location = EXCLUDED.location,
|
||||
wallet_id = EXCLUDED.wallet_id,
|
||||
branch_manager_id = EXCLUDED.branch_manager_id,
|
||||
company_id = EXCLUDED.company_id,
|
||||
is_self_owned = EXCLUDED.is_self_owned,
|
||||
profit_percent = EXCLUDED.profit_percent,
|
||||
is_active = EXCLUDED.is_active,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
148
db/data/002_veli_user.sql
Normal file
148
db/data/002_veli_user.sql
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
-- Users
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
5,
|
||||
'Test',
|
||||
'Veli',
|
||||
'test.veli@example.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
),
|
||||
(
|
||||
6,
|
||||
'Kirubel',
|
||||
'Kibru',
|
||||
'modernkibru @gmail.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET first_name = EXCLUDED.first_name,
|
||||
last_name = EXCLUDED.last_name,
|
||||
email = EXCLUDED.email,
|
||||
phone_number = EXCLUDED.phone_number,
|
||||
password = EXCLUDED.password,
|
||||
role = EXCLUDED.role,
|
||||
email_verified = EXCLUDED.email_verified,
|
||||
phone_verified = EXCLUDED.phone_verified,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at,
|
||||
suspended = EXCLUDED.suspended,
|
||||
company_id = EXCLUDED.company_id;
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
5,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'regular_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
6,
|
||||
5000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'static_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
7,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'regular_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
8,
|
||||
5000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'static_wallet',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET balance = EXCLUDED.balance,
|
||||
is_withdraw = EXCLUDED.is_withdraw,
|
||||
is_bettable = EXCLUDED.is_bettable,
|
||||
is_transferable = EXCLUDED.is_transferable,
|
||||
user_id = EXCLUDED.user_id,
|
||||
type = EXCLUDED.type,
|
||||
currency = EXCLUDED.currency,
|
||||
is_active = EXCLUDED.is_active,
|
||||
created_at = EXCLUDED.created_at,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
-- Customer Wallets
|
||||
INSERT INTO customer_wallets (
|
||||
id,
|
||||
customer_id,
|
||||
regular_wallet_id,
|
||||
static_wallet_id
|
||||
)
|
||||
VALUES (2, 5, 5, 6),
|
||||
(3, 6, 7, 8) ON CONFLICT (id) DO
|
||||
UPDATE
|
||||
SET customer_id = EXCLUDED.customer_id,
|
||||
regular_wallet_id = EXCLUDED.regular_wallet_id,
|
||||
static_wallet_id = EXCLUDED.static_wallet_id;
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
BEGIN;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
-- Users
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'John',
|
||||
'Doe',
|
||||
'john.doe@example.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
2,
|
||||
'Test',
|
||||
'Admin',
|
||||
'test.admin@gmail.com',
|
||||
'0988554466',
|
||||
crypt('password123', gen_salt('bf'))::bytea,
|
||||
'admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
),
|
||||
(
|
||||
3,
|
||||
'Samuel',
|
||||
'Tariku',
|
||||
'cybersamt@gmail.com',
|
||||
'0911111111',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
4,
|
||||
'Kirubel',
|
||||
'Kibru',
|
||||
'kirubel.jkl679@gmail.com',
|
||||
'0911554486',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
5,
|
||||
'Test',
|
||||
'Veli',
|
||||
'test.veli@example.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
-- Supported Operations
|
||||
INSERT INTO supported_operations (id, name, description)
|
||||
VALUES (1, 'SportBook', 'Sportbook operations'),
|
||||
(2, 'Virtual', 'Virtual operations');
|
||||
-- Wallets
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'regular',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
2,
|
||||
5000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'static',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
3,
|
||||
20000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'company_main',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
4,
|
||||
15000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'branch_main',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
-- Customer Wallets
|
||||
INSERT INTO customer_wallets (
|
||||
id,
|
||||
customer_id,
|
||||
regular_wallet_id,
|
||||
static_wallet_id
|
||||
)
|
||||
VALUES (1, 1, 1, 2);
|
||||
-- Company
|
||||
INSERT INTO companies (
|
||||
id,
|
||||
name,
|
||||
slug,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'FortuneBets',
|
||||
'fortunebets',
|
||||
2,
|
||||
3,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
-- Branch
|
||||
INSERT INTO branches (
|
||||
id,
|
||||
name,
|
||||
location,
|
||||
wallet_id,
|
||||
branch_manager_id,
|
||||
company_id,
|
||||
is_self_owned,
|
||||
profit_percent,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'Test Branch',
|
||||
'addis_ababa',
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
TRUE,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
COMMIT;
|
||||
|
|
@ -21,14 +21,18 @@ CREATE TABLE IF NOT EXISTS users (
|
|||
UNIQUE (email, company_id),
|
||||
UNIQUE (phone_number, company_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS virtual_game_providers (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
provider_id VARCHAR(100) UNIQUE NOT NULL, -- providerId from Veli Games
|
||||
provider_name VARCHAR(255) NOT NULL, -- providerName
|
||||
logo_dark TEXT, -- logoForDark (URL)
|
||||
logo_light TEXT, -- logoForLight (URL)
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE, -- allow enabling/disabling providers
|
||||
provider_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
-- providerId from Veli Games
|
||||
provider_name VARCHAR(255) NOT NULL,
|
||||
-- providerName
|
||||
logo_dark TEXT,
|
||||
-- logoForDark (URL)
|
||||
logo_light TEXT,
|
||||
-- logoForLight (URL)
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
-- allow enabling/disabling providers
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
|
@ -40,7 +44,14 @@ CREATE TABLE IF NOT EXISTS wallets (
|
|||
is_bettable BOOLEAN NOT NULL,
|
||||
is_transferable BOOLEAN NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
type VARCHAR(255) NOT NULL,
|
||||
type TEXT NOT NULL CHECK (
|
||||
type IN (
|
||||
'regular_wallet',
|
||||
'static_wallet',
|
||||
'branch_wallet',
|
||||
'company_wallet'
|
||||
)
|
||||
),
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
|
|
@ -265,10 +276,7 @@ CREATE TABLE IF NOT EXISTS branch_cashiers (
|
|||
branch_id BIGINT NOT NULL,
|
||||
UNIQUE (user_id, branch_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS branch_locations (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS branch_locations (key TEXT PRIMARY KEY, value TEXT NOT NULL);
|
||||
CREATE TABLE events (
|
||||
id TEXT PRIMARY KEY,
|
||||
sport_id INT NOT NULL,
|
||||
|
|
@ -291,13 +299,7 @@ CREATE TABLE events (
|
|||
status TEXT NOT NULL,
|
||||
fetched_at TIMESTAMP DEFAULT now (),
|
||||
source TEXT NOT NULL DEFAULT 'b365api' CHECK (
|
||||
source IN (
|
||||
'b365api',
|
||||
'bfair',
|
||||
'1xbet',
|
||||
'bwin',
|
||||
'enetpulse'
|
||||
)
|
||||
source IN ('b365api', 'bfair', '1xbet', 'bwin', 'enetpulse')
|
||||
),
|
||||
default_is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
default_is_featured BOOLEAN NOT NULL DEFAULT false,
|
||||
|
|
|
|||
|
|
@ -18,17 +18,19 @@ CREATE TABLE IF NOT EXISTS referral_settings (
|
|||
);
|
||||
CREATE TABLE IF NOT EXISTS referrals (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
company_id BIGINT NOT NULL REFERENCES companies (id) ON
|
||||
DELETE CASCADE,
|
||||
referral_code VARCHAR(10) NOT NULL UNIQUE,
|
||||
referrer_id VARCHAR(255) NOT NULL,
|
||||
referred_id VARCHAR(255) UNIQUE,
|
||||
referrer_id BIGINT NOT NULL REFERENCES users (id),
|
||||
referred_id BIGINT UNIQUE REFERENCES users (id),
|
||||
status ReferralStatus NOT NULL DEFAULT 'PENDING',
|
||||
reward_amount DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
cashback_amount DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
-- FOREIGN KEY (referrer_id) REFERENCES users (id),
|
||||
expires_at TIMESTAMPTZ NOT NULL -- FOREIGN KEY (referrer_id) REFERENCES users (id),
|
||||
-- FOREIGN KEY (referred_id) REFERENCES users (id),
|
||||
,
|
||||
CONSTRAINT reward_amount_positive CHECK (reward_amount >= 0),
|
||||
CONSTRAINT cashback_amount_positive CHECK (cashback_amount >= 0)
|
||||
);
|
||||
|
|
@ -38,7 +40,7 @@ CREATE INDEX idx_referrals_status ON referrals (status);
|
|||
ALTER TABLE users
|
||||
ADD COLUMN IF NOT EXISTS referral_code VARCHAR(10) UNIQUE,
|
||||
ADD COLUMN IF NOT EXISTS referred_by VARCHAR(10);
|
||||
-- Modify wallet table to track bonus money separately
|
||||
-- Modify wallet TABLE to track bonus money separately
|
||||
ALTER TABLE wallets
|
||||
ADD COLUMN IF NOT EXISTS bonus_balance DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
ADD COLUMN IF NOT EXISTS cash_balance DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
-- Settings Initial Data
|
||||
INSERT INTO global_settings (key, value)
|
||||
VALUES ('sms_provider', 'afro_message'),
|
||||
('max_number_of_outcomes', '30'),
|
||||
('bet_amount_limit', '10000000'),
|
||||
('daily_ticket_limit', '50'),
|
||||
('total_winnings_limit', '1000000'),
|
||||
('amount_for_bet_referral', '1000000'),
|
||||
('cashback_amount_cap', '1000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
-- -- Settings Initial Data
|
||||
-- INSERT INTO global_settings (key, value)
|
||||
-- VALUES ('sms_provider', 'afro_message'),
|
||||
-- ('max_number_of_outcomes', '30'),
|
||||
-- ('bet_amount_limit', '10000000'),
|
||||
-- ('daily_ticket_limit', '50'),
|
||||
-- ('total_winnings_limit', '1000000'),
|
||||
-- ('amount_for_bet_referral', '1000000'),
|
||||
-- ('cashback_amount_cap', '1000') ON CONFLICT (key) DO
|
||||
-- UPDATE
|
||||
-- SET value = EXCLUDED.value;
|
||||
|
|
@ -1,75 +1,75 @@
|
|||
-- 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,', 'Alamata,'),
|
||||
('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;
|
||||
-- -- 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,', 'Alamata,'),
|
||||
-- ('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;
|
||||
|
|
@ -1,218 +1,220 @@
|
|||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
-- Users
|
||||
INSERT INTO users (
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
password,
|
||||
role,
|
||||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'John',
|
||||
'Doe',
|
||||
'john.doe@example.com',
|
||||
NULL,
|
||||
crypt('password123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
2,
|
||||
'Test',
|
||||
'Admin',
|
||||
'test.admin@gmail.com',
|
||||
'0988554466',
|
||||
crypt('password123', gen_salt('bf'))::bytea,
|
||||
'admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
1
|
||||
),
|
||||
(
|
||||
3,
|
||||
'Samuel',
|
||||
'Tariku',
|
||||
'cybersamt@gmail.com',
|
||||
'0911111111',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
4,
|
||||
'Kirubel',
|
||||
'Kibru',
|
||||
'kirubel.jkl679@gmail.com',
|
||||
'0911554486',
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'super_admin',
|
||||
TRUE,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
),
|
||||
(
|
||||
5,
|
||||
'Test',
|
||||
'Veli',
|
||||
'test.veli@example.com',
|
||||
NULL,
|
||||
crypt('password@123', gen_salt('bf'))::bytea,
|
||||
'customer',
|
||||
TRUE,
|
||||
FALSE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
-- Supported Operations
|
||||
INSERT INTO supported_operations (id, name, description)
|
||||
VALUES (1, 'SportBook', 'Sportbook operations'),
|
||||
(2, 'Virtual', 'Virtual operations');
|
||||
-- Wallets
|
||||
INSERT INTO wallets (
|
||||
id,
|
||||
balance,
|
||||
is_withdraw,
|
||||
is_bettable,
|
||||
is_transferable,
|
||||
user_id,
|
||||
type,
|
||||
currency,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
10000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'regular',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
2,
|
||||
5000,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
1,
|
||||
'static',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
3,
|
||||
20000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'company_main',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
),
|
||||
(
|
||||
4,
|
||||
15000,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
2,
|
||||
'branch_main',
|
||||
'ETB',
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
-- Customer Wallets
|
||||
INSERT INTO customer_wallets (
|
||||
id,
|
||||
customer_id,
|
||||
regular_wallet_id,
|
||||
static_wallet_id
|
||||
)
|
||||
VALUES (1, 1, 1, 2);
|
||||
-- Company
|
||||
INSERT INTO companies (
|
||||
id,
|
||||
name,
|
||||
admin_id,
|
||||
wallet_id,
|
||||
deducted_percentage,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'Test Company',
|
||||
2,
|
||||
3,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
-- Branch
|
||||
INSERT INTO branches (
|
||||
id,
|
||||
name,
|
||||
location,
|
||||
wallet_id,
|
||||
branch_manager_id,
|
||||
company_id,
|
||||
is_self_owned,
|
||||
profit_percent,
|
||||
is_active,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
'Test Branch',
|
||||
'addis_ababa',
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
TRUE,
|
||||
0.10,
|
||||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
-- CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
-- -- Users
|
||||
-- INSERT INTO users (
|
||||
-- id,
|
||||
-- first_name,
|
||||
-- last_name,
|
||||
-- email,
|
||||
-- phone_number,
|
||||
-- password,
|
||||
-- role,
|
||||
-- email_verified,
|
||||
-- phone_verified,
|
||||
-- created_at,
|
||||
-- updated_at,
|
||||
-- suspended,
|
||||
-- company_id
|
||||
-- )
|
||||
-- VALUES (
|
||||
-- 1,
|
||||
-- 'John',
|
||||
-- 'Doe',
|
||||
-- 'john.doe@example.com',
|
||||
-- NULL,
|
||||
-- crypt('password@123', gen_salt('bf'))::bytea,
|
||||
-- 'customer',
|
||||
-- TRUE,
|
||||
-- FALSE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- FALSE,
|
||||
-- 1
|
||||
-- ),
|
||||
-- (
|
||||
-- 2,
|
||||
-- 'Test',
|
||||
-- 'Admin',
|
||||
-- 'test.admin@gmail.com',
|
||||
-- '0988554466',
|
||||
-- crypt('password@123', gen_salt('bf'))::bytea,
|
||||
-- 'admin',
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- FALSE,
|
||||
-- 1
|
||||
-- ),
|
||||
-- (
|
||||
-- 3,
|
||||
-- 'Samuel',
|
||||
-- 'Tariku',
|
||||
-- 'cybersamt@gmail.com',
|
||||
-- '0911111111',
|
||||
-- crypt('password@123', gen_salt('bf'))::bytea,
|
||||
-- 'super_admin',
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- FALSE,
|
||||
-- NULL
|
||||
-- ),
|
||||
-- (
|
||||
-- 4,
|
||||
-- 'Kirubel',
|
||||
-- 'Kibru',
|
||||
-- 'kirubel.jkl679@gmail.com',
|
||||
-- '0911554486',
|
||||
-- crypt('password@123', gen_salt('bf'))::bytea,
|
||||
-- 'super_admin',
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- FALSE,
|
||||
-- NULL
|
||||
-- ),
|
||||
-- (
|
||||
-- 5,
|
||||
-- 'Test',
|
||||
-- 'Veli',
|
||||
-- 'test.veli@example.com',
|
||||
-- NULL,
|
||||
-- crypt('password@123', gen_salt('bf'))::bytea,
|
||||
-- 'customer',
|
||||
-- TRUE,
|
||||
-- FALSE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- FALSE,
|
||||
-- 1
|
||||
-- );
|
||||
-- -- Supported Operations
|
||||
-- INSERT INTO supported_operations (id, name, description)
|
||||
-- VALUES (1, 'SportBook', 'Sportbook operations'),
|
||||
-- (2, 'Virtual', 'Virtual operations');
|
||||
-- -- Wallets
|
||||
-- INSERT INTO wallets (
|
||||
-- id,
|
||||
-- balance,
|
||||
-- is_withdraw,
|
||||
-- is_bettable,
|
||||
-- is_transferable,
|
||||
-- user_id,
|
||||
-- type,
|
||||
-- currency,
|
||||
-- is_active,
|
||||
-- created_at,
|
||||
-- updated_at
|
||||
-- )
|
||||
-- VALUES (
|
||||
-- 1,
|
||||
-- 10000,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- 1,
|
||||
-- 'regular_wallet',
|
||||
-- 'ETB',
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- ),
|
||||
-- (
|
||||
-- 2,
|
||||
-- 5000,
|
||||
-- FALSE,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- 1,
|
||||
-- 'static_wallet',
|
||||
-- 'ETB',
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- ),
|
||||
-- (
|
||||
-- 3,
|
||||
-- 20000,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- 2,
|
||||
-- 'company_wallet',
|
||||
-- 'ETB',
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- ),
|
||||
-- (
|
||||
-- 4,
|
||||
-- 15000,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- TRUE,
|
||||
-- 2,
|
||||
-- 'branch_wallet',
|
||||
-- 'ETB',
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- );
|
||||
-- -- Customer Wallets
|
||||
-- INSERT INTO customer_wallets (
|
||||
-- id,
|
||||
-- customer_id,
|
||||
-- regular_wallet_id,
|
||||
-- static_wallet_id
|
||||
-- )
|
||||
-- VALUES (1, 1, 1, 2);
|
||||
-- -- Company
|
||||
-- INSERT INTO companies (
|
||||
-- id,
|
||||
-- name,
|
||||
-- slug,
|
||||
-- admin_id,
|
||||
-- wallet_id,
|
||||
-- deducted_percentage,
|
||||
-- is_active,
|
||||
-- created_at,
|
||||
-- updated_at
|
||||
-- )
|
||||
-- VALUES (
|
||||
-- 1,
|
||||
-- 'FortuneBets',
|
||||
-- 'fortunebets',
|
||||
-- 2,
|
||||
-- 3,
|
||||
-- 0.10,
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- );
|
||||
-- -- Branch
|
||||
-- INSERT INTO branches (
|
||||
-- id,
|
||||
-- name,
|
||||
-- location,
|
||||
-- wallet_id,
|
||||
-- branch_manager_id,
|
||||
-- company_id,
|
||||
-- is_self_owned,
|
||||
-- profit_percent,
|
||||
-- is_active,
|
||||
-- created_at,
|
||||
-- updated_at
|
||||
-- )
|
||||
-- VALUES (
|
||||
-- 1,
|
||||
-- 'Test Branch',
|
||||
-- 'addis_ababa',
|
||||
-- 4,
|
||||
-- 2,
|
||||
-- 1,
|
||||
-- TRUE,
|
||||
-- 0.10,
|
||||
-- TRUE,
|
||||
-- CURRENT_TIMESTAMP,
|
||||
-- CURRENT_TIMESTAMP
|
||||
-- );
|
||||
|
|
@ -2,50 +2,55 @@
|
|||
INSERT INTO referrals (
|
||||
referral_code,
|
||||
referrer_id,
|
||||
company_id,
|
||||
status,
|
||||
reward_amount,
|
||||
expires_at
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
) RETURNING *;
|
||||
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *;
|
||||
-- name: GetReferralByCode :one
|
||||
SELECT * FROM referrals
|
||||
SELECT *
|
||||
FROM referrals
|
||||
WHERE referral_code = $1;
|
||||
|
||||
-- name: UpdateReferral :one
|
||||
UPDATE referrals
|
||||
SET
|
||||
referred_id = $2,
|
||||
SET referred_id = $2,
|
||||
status = $3,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateReferralCode :exec
|
||||
UPDATE users
|
||||
SET
|
||||
referral_code = $2,
|
||||
SET referral_code = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: GetReferralStats :one
|
||||
SELECT
|
||||
COUNT(*) as total_referrals,
|
||||
COUNT(CASE WHEN status = 'COMPLETED' THEN 1 END) as completed_referrals,
|
||||
COALESCE(SUM(reward_amount), 0) as total_reward_earned,
|
||||
COALESCE(SUM(CASE WHEN status = 'PENDING' THEN reward_amount END), 0) as pending_rewards
|
||||
SELECT COUNT(*) AS total_referrals,
|
||||
COUNT(
|
||||
CASE
|
||||
WHEN status = 'COMPLETED' THEN 1
|
||||
END
|
||||
) AS completed_referrals,
|
||||
COALESCE(SUM(reward_amount), 0) AS total_reward_earned,
|
||||
COALESCE(
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 'PENDING' THEN reward_amount
|
||||
END
|
||||
),
|
||||
0
|
||||
) AS pending_rewards
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1;
|
||||
|
||||
WHERE referrer_id = $1
|
||||
AND company_id = $2;
|
||||
-- name: GetReferralSettings :one
|
||||
SELECT * FROM referral_settings
|
||||
SELECT *
|
||||
FROM referral_settings
|
||||
LIMIT 1;
|
||||
|
||||
-- name: UpdateReferralSettings :one
|
||||
UPDATE referral_settings
|
||||
SET
|
||||
referral_reward_amount = $2,
|
||||
SET referral_reward_amount = $2,
|
||||
cashback_percentage = $3,
|
||||
bet_referral_bonus_percentage = $4,
|
||||
max_referrals = $5,
|
||||
|
|
@ -54,7 +59,6 @@ SET
|
|||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateReferralSettings :one
|
||||
INSERT INTO referral_settings (
|
||||
referral_reward_amount,
|
||||
|
|
@ -63,15 +67,21 @@ INSERT INTO referral_settings (
|
|||
bet_referral_bonus_percentage,
|
||||
expires_after_days,
|
||||
updated_by
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6
|
||||
) RETURNING *;
|
||||
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *;
|
||||
-- name: GetReferralByReferredID :one
|
||||
SELECT * FROM referrals WHERE referred_id = $1 LIMIT 1;
|
||||
|
||||
SELECT *
|
||||
FROM referrals
|
||||
WHERE referred_id = $1
|
||||
LIMIT 1;
|
||||
-- name: GetActiveReferralByReferrerID :one
|
||||
SELECT * FROM referrals WHERE referrer_id = $1 AND status = 'PENDING' LIMIT 1;
|
||||
|
||||
SELECT *
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1
|
||||
AND status = 'PENDING'
|
||||
LIMIT 1;
|
||||
-- name: GetReferralCountByID :one
|
||||
SELECT count(*) FROM referrals WHERE referrer_id = $1;
|
||||
SELECT COUNT(*)
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1;
|
||||
|
|
@ -193,7 +193,7 @@ SET password = $1,
|
|||
WHERE (
|
||||
email = $2
|
||||
OR phone_number = $3
|
||||
AND company_id = $4
|
||||
AND company_id = $5
|
||||
);
|
||||
-- name: GetAdminByCompanyID :one
|
||||
SELECT users.*
|
||||
|
|
|
|||
|
|
@ -540,9 +540,10 @@ type Otp struct {
|
|||
|
||||
type Referral struct {
|
||||
ID int64 `json:"id"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
ReferralCode string `json:"referral_code"`
|
||||
ReferrerID string `json:"referrer_id"`
|
||||
ReferredID pgtype.Text `json:"referred_id"`
|
||||
ReferrerID int64 `json:"referrer_id"`
|
||||
ReferredID pgtype.Int8 `json:"referred_id"`
|
||||
Status Referralstatus `json:"status"`
|
||||
RewardAmount pgtype.Numeric `json:"reward_amount"`
|
||||
CashbackAmount pgtype.Numeric `json:"cashback_amount"`
|
||||
|
|
|
|||
|
|
@ -15,17 +15,19 @@ const CreateReferral = `-- name: CreateReferral :one
|
|||
INSERT INTO referrals (
|
||||
referral_code,
|
||||
referrer_id,
|
||||
company_id,
|
||||
status,
|
||||
reward_amount,
|
||||
expires_at
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
) RETURNING id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, company_id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
`
|
||||
|
||||
type CreateReferralParams struct {
|
||||
ReferralCode string `json:"referral_code"`
|
||||
ReferrerID string `json:"referrer_id"`
|
||||
ReferrerID int64 `json:"referrer_id"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
Status Referralstatus `json:"status"`
|
||||
RewardAmount pgtype.Numeric `json:"reward_amount"`
|
||||
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
||||
|
|
@ -35,6 +37,7 @@ func (q *Queries) CreateReferral(ctx context.Context, arg CreateReferralParams)
|
|||
row := q.db.QueryRow(ctx, CreateReferral,
|
||||
arg.ReferralCode,
|
||||
arg.ReferrerID,
|
||||
arg.CompanyID,
|
||||
arg.Status,
|
||||
arg.RewardAmount,
|
||||
arg.ExpiresAt,
|
||||
|
|
@ -42,6 +45,7 @@ func (q *Queries) CreateReferral(ctx context.Context, arg CreateReferralParams)
|
|||
var i Referral
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CompanyID,
|
||||
&i.ReferralCode,
|
||||
&i.ReferrerID,
|
||||
&i.ReferredID,
|
||||
|
|
@ -63,9 +67,9 @@ INSERT INTO referral_settings (
|
|||
bet_referral_bonus_percentage,
|
||||
expires_after_days,
|
||||
updated_by
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6
|
||||
) RETURNING id, referral_reward_amount, cashback_percentage, bet_referral_bonus_percentage, max_referrals, expires_after_days, updated_by, created_at, updated_at, version
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, referral_reward_amount, cashback_percentage, bet_referral_bonus_percentage, max_referrals, expires_after_days, updated_by, created_at, updated_at, version
|
||||
`
|
||||
|
||||
type CreateReferralSettingsParams struct {
|
||||
|
|
@ -103,14 +107,19 @@ func (q *Queries) CreateReferralSettings(ctx context.Context, arg CreateReferral
|
|||
}
|
||||
|
||||
const GetActiveReferralByReferrerID = `-- name: GetActiveReferralByReferrerID :one
|
||||
SELECT id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at FROM referrals WHERE referrer_id = $1 AND status = 'PENDING' LIMIT 1
|
||||
SELECT id, company_id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1
|
||||
AND status = 'PENDING'
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetActiveReferralByReferrerID(ctx context.Context, referrerID string) (Referral, error) {
|
||||
func (q *Queries) GetActiveReferralByReferrerID(ctx context.Context, referrerID int64) (Referral, error) {
|
||||
row := q.db.QueryRow(ctx, GetActiveReferralByReferrerID, referrerID)
|
||||
var i Referral
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CompanyID,
|
||||
&i.ReferralCode,
|
||||
&i.ReferrerID,
|
||||
&i.ReferredID,
|
||||
|
|
@ -125,7 +134,8 @@ func (q *Queries) GetActiveReferralByReferrerID(ctx context.Context, referrerID
|
|||
}
|
||||
|
||||
const GetReferralByCode = `-- name: GetReferralByCode :one
|
||||
SELECT id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at FROM referrals
|
||||
SELECT id, company_id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
FROM referrals
|
||||
WHERE referral_code = $1
|
||||
`
|
||||
|
||||
|
|
@ -134,6 +144,7 @@ func (q *Queries) GetReferralByCode(ctx context.Context, referralCode string) (R
|
|||
var i Referral
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CompanyID,
|
||||
&i.ReferralCode,
|
||||
&i.ReferrerID,
|
||||
&i.ReferredID,
|
||||
|
|
@ -148,14 +159,18 @@ func (q *Queries) GetReferralByCode(ctx context.Context, referralCode string) (R
|
|||
}
|
||||
|
||||
const GetReferralByReferredID = `-- name: GetReferralByReferredID :one
|
||||
SELECT id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at FROM referrals WHERE referred_id = $1 LIMIT 1
|
||||
SELECT id, company_id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
FROM referrals
|
||||
WHERE referred_id = $1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetReferralByReferredID(ctx context.Context, referredID pgtype.Text) (Referral, error) {
|
||||
func (q *Queries) GetReferralByReferredID(ctx context.Context, referredID pgtype.Int8) (Referral, error) {
|
||||
row := q.db.QueryRow(ctx, GetReferralByReferredID, referredID)
|
||||
var i Referral
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CompanyID,
|
||||
&i.ReferralCode,
|
||||
&i.ReferrerID,
|
||||
&i.ReferredID,
|
||||
|
|
@ -170,10 +185,12 @@ func (q *Queries) GetReferralByReferredID(ctx context.Context, referredID pgtype
|
|||
}
|
||||
|
||||
const GetReferralCountByID = `-- name: GetReferralCountByID :one
|
||||
SELECT count(*) FROM referrals WHERE referrer_id = $1
|
||||
SELECT COUNT(*)
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetReferralCountByID(ctx context.Context, referrerID string) (int64, error) {
|
||||
func (q *Queries) GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetReferralCountByID, referrerID)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
|
|
@ -181,7 +198,8 @@ func (q *Queries) GetReferralCountByID(ctx context.Context, referrerID string) (
|
|||
}
|
||||
|
||||
const GetReferralSettings = `-- name: GetReferralSettings :one
|
||||
SELECT id, referral_reward_amount, cashback_percentage, bet_referral_bonus_percentage, max_referrals, expires_after_days, updated_by, created_at, updated_at, version FROM referral_settings
|
||||
SELECT id, referral_reward_amount, cashback_percentage, bet_referral_bonus_percentage, max_referrals, expires_after_days, updated_by, created_at, updated_at, version
|
||||
FROM referral_settings
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
|
|
@ -204,15 +222,31 @@ func (q *Queries) GetReferralSettings(ctx context.Context) (ReferralSetting, err
|
|||
}
|
||||
|
||||
const GetReferralStats = `-- name: GetReferralStats :one
|
||||
SELECT
|
||||
COUNT(*) as total_referrals,
|
||||
COUNT(CASE WHEN status = 'COMPLETED' THEN 1 END) as completed_referrals,
|
||||
COALESCE(SUM(reward_amount), 0) as total_reward_earned,
|
||||
COALESCE(SUM(CASE WHEN status = 'PENDING' THEN reward_amount END), 0) as pending_rewards
|
||||
SELECT COUNT(*) AS total_referrals,
|
||||
COUNT(
|
||||
CASE
|
||||
WHEN status = 'COMPLETED' THEN 1
|
||||
END
|
||||
) AS completed_referrals,
|
||||
COALESCE(SUM(reward_amount), 0) AS total_reward_earned,
|
||||
COALESCE(
|
||||
SUM(
|
||||
CASE
|
||||
WHEN status = 'PENDING' THEN reward_amount
|
||||
END
|
||||
),
|
||||
0
|
||||
) AS pending_rewards
|
||||
FROM referrals
|
||||
WHERE referrer_id = $1
|
||||
AND company_id = $2
|
||||
`
|
||||
|
||||
type GetReferralStatsParams struct {
|
||||
ReferrerID int64 `json:"referrer_id"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
}
|
||||
|
||||
type GetReferralStatsRow struct {
|
||||
TotalReferrals int64 `json:"total_referrals"`
|
||||
CompletedReferrals int64 `json:"completed_referrals"`
|
||||
|
|
@ -220,8 +254,8 @@ type GetReferralStatsRow struct {
|
|||
PendingRewards interface{} `json:"pending_rewards"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetReferralStats(ctx context.Context, referrerID string) (GetReferralStatsRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetReferralStats, referrerID)
|
||||
func (q *Queries) GetReferralStats(ctx context.Context, arg GetReferralStatsParams) (GetReferralStatsRow, error) {
|
||||
row := q.db.QueryRow(ctx, GetReferralStats, arg.ReferrerID, arg.CompanyID)
|
||||
var i GetReferralStatsRow
|
||||
err := row.Scan(
|
||||
&i.TotalReferrals,
|
||||
|
|
@ -234,17 +268,16 @@ func (q *Queries) GetReferralStats(ctx context.Context, referrerID string) (GetR
|
|||
|
||||
const UpdateReferral = `-- name: UpdateReferral :one
|
||||
UPDATE referrals
|
||||
SET
|
||||
referred_id = $2,
|
||||
SET referred_id = $2,
|
||||
status = $3,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
RETURNING id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
RETURNING id, company_id, referral_code, referrer_id, referred_id, status, reward_amount, cashback_amount, created_at, updated_at, expires_at
|
||||
`
|
||||
|
||||
type UpdateReferralParams struct {
|
||||
ID int64 `json:"id"`
|
||||
ReferredID pgtype.Text `json:"referred_id"`
|
||||
ReferredID pgtype.Int8 `json:"referred_id"`
|
||||
Status Referralstatus `json:"status"`
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +286,7 @@ func (q *Queries) UpdateReferral(ctx context.Context, arg UpdateReferralParams)
|
|||
var i Referral
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CompanyID,
|
||||
&i.ReferralCode,
|
||||
&i.ReferrerID,
|
||||
&i.ReferredID,
|
||||
|
|
@ -268,8 +302,7 @@ func (q *Queries) UpdateReferral(ctx context.Context, arg UpdateReferralParams)
|
|||
|
||||
const UpdateReferralCode = `-- name: UpdateReferralCode :exec
|
||||
UPDATE users
|
||||
SET
|
||||
referral_code = $2,
|
||||
SET referral_code = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -286,8 +319,7 @@ func (q *Queries) UpdateReferralCode(ctx context.Context, arg UpdateReferralCode
|
|||
|
||||
const UpdateReferralSettings = `-- name: UpdateReferralSettings :one
|
||||
UPDATE referral_settings
|
||||
SET
|
||||
referral_reward_amount = $2,
|
||||
SET referral_reward_amount = $2,
|
||||
cashback_percentage = $3,
|
||||
bet_referral_bonus_percentage = $4,
|
||||
max_referrals = $5,
|
||||
|
|
|
|||
|
|
@ -587,7 +587,7 @@ SET password = $1,
|
|||
WHERE (
|
||||
email = $2
|
||||
OR phone_number = $3
|
||||
AND company_id = $4
|
||||
AND company_id = $5
|
||||
)
|
||||
`
|
||||
|
||||
|
|
@ -596,6 +596,7 @@ type UpdatePasswordParams struct {
|
|||
Email pgtype.Text `json:"email"`
|
||||
PhoneNumber pgtype.Text `json:"phone_number"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error {
|
||||
|
|
@ -604,6 +605,7 @@ func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams)
|
|||
arg.Email,
|
||||
arg.PhoneNumber,
|
||||
arg.UpdatedAt,
|
||||
arg.CompanyID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,3 +10,10 @@ type RefreshToken struct {
|
|||
CreatedAt time.Time
|
||||
Revoked bool
|
||||
}
|
||||
|
||||
// I used this because i was getting an error with the ValidInt64
|
||||
// when it was being unmarshaled by the jwt
|
||||
type NullJwtInt64 struct {
|
||||
Value int64
|
||||
Valid bool
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,9 @@ type ReferralSettingsReq struct {
|
|||
type Referral struct {
|
||||
ID int64
|
||||
ReferralCode string
|
||||
ReferrerID string
|
||||
ReferredID *string
|
||||
ReferrerID int64
|
||||
CompanyID int64
|
||||
ReferredID *int64
|
||||
Status ReferralStatus
|
||||
RewardAmount float64
|
||||
CashbackAmount float64
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ const (
|
|||
RoleBranchManager Role = "branch_manager"
|
||||
RoleCustomer Role = "customer"
|
||||
RoleCashier Role = "cashier"
|
||||
RoleTransactionApprover Role = "transaction_approver"
|
||||
)
|
||||
|
||||
func (r Role) IsValid() bool {
|
||||
switch r {
|
||||
case RoleSuperAdmin, RoleAdmin, RoleBranchManager, RoleCustomer, RoleCashier:
|
||||
case RoleSuperAdmin, RoleAdmin, RoleBranchManager, RoleCustomer, RoleCashier, RoleTransactionApprover:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ type User struct {
|
|||
UpdatedAt time.Time
|
||||
SuspendedAt time.Time
|
||||
Suspended bool
|
||||
CompanyID ValidInt64 //This should be null
|
||||
CompanyID ValidInt64
|
||||
}
|
||||
|
||||
type UserFilter struct {
|
||||
|
|
@ -36,7 +36,6 @@ type UserFilter struct {
|
|||
CreatedAfter ValidTime
|
||||
}
|
||||
|
||||
|
||||
type RegisterUserReq struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
|
|
@ -65,6 +64,7 @@ type ResetPasswordReq struct {
|
|||
Password string
|
||||
Otp string
|
||||
OtpMedium OtpMedium
|
||||
CompanyID int64
|
||||
}
|
||||
type UpdateUserReq struct {
|
||||
UserId int64
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ type CreateCustomerWallet struct {
|
|||
type WalletType string
|
||||
|
||||
const (
|
||||
CustomerWalletType WalletType = "customer_wallet"
|
||||
RegularWalletType WalletType = "regular_wallet"
|
||||
StaticWalletType WalletType = "static_wallet"
|
||||
BranchWalletType WalletType = "branch_wallet"
|
||||
CompanyWalletType WalletType = "company_wallet"
|
||||
)
|
||||
|
|
@ -92,18 +93,18 @@ const (
|
|||
)
|
||||
|
||||
type DirectDeposit struct {
|
||||
ID int64
|
||||
CustomerID int64
|
||||
WalletID int64
|
||||
Wallet Wallet // Joined data
|
||||
Amount Currency
|
||||
BankReference string
|
||||
SenderAccount string
|
||||
Status DirectDepositStatus
|
||||
CreatedAt time.Time
|
||||
VerifiedBy *int64 // Nullable
|
||||
VerificationNotes string
|
||||
VerifiedAt *time.Time // Nullable
|
||||
ID int64 `json:"id"`
|
||||
CustomerID int64 `json:"customer_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
Wallet Wallet `json:"wallet"`
|
||||
Amount Currency `json:"amount"`
|
||||
BankReference string `json:"bank_reference"`
|
||||
SenderAccount string `json:"sender_account"`
|
||||
Status DirectDepositStatus `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
VerifiedBy *int64 `json:"verified_by"`
|
||||
VerificationNotes string `json:"verification_notes"`
|
||||
VerifiedAt *time.Time `json:"verified_at"`
|
||||
}
|
||||
|
||||
type CreateDirectDeposit struct {
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ type ReferralRepository interface {
|
|||
CreateReferral(ctx context.Context, referral *domain.Referral) error
|
||||
GetReferralByCode(ctx context.Context, code string) (*domain.Referral, error)
|
||||
UpdateReferral(ctx context.Context, referral *domain.Referral) error
|
||||
GetReferralStats(ctx context.Context, userID string) (*domain.ReferralStats, error)
|
||||
GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error)
|
||||
GetSettings(ctx context.Context) (*domain.ReferralSettings, error)
|
||||
UpdateSettings(ctx context.Context, settings *domain.ReferralSettings) error
|
||||
CreateSettings(ctx context.Context, settings *domain.ReferralSettings) error
|
||||
GetReferralByReferredID(ctx context.Context, referredID string) (*domain.Referral, error) // New method
|
||||
GetReferralCountByID(ctx context.Context, referrerID string) (int64, error)
|
||||
GetActiveReferralByReferrerID(ctx context.Context, referrerID string) (*domain.Referral, error)
|
||||
GetReferralByReferredID(ctx context.Context, referredID int64) (*domain.Referral, error)
|
||||
GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error)
|
||||
GetActiveReferralByReferrerID(ctx context.Context, referrerID int64) (*domain.Referral, error)
|
||||
UpdateUserReferalCode(ctx context.Context, codedata domain.UpdateUserReferalCode) error
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +58,7 @@ func (r *ReferralRepo) CreateReferral(ctx context.Context, referral *domain.Refe
|
|||
Status: dbgen.Referralstatus(referral.Status),
|
||||
RewardAmount: rewardAmount,
|
||||
ExpiresAt: pgtype.Timestamptz{Time: referral.ExpiresAt, Valid: true},
|
||||
CompanyID: referral.CompanyID,
|
||||
}
|
||||
|
||||
_, err := r.store.queries.CreateReferral(ctx, params)
|
||||
|
|
@ -76,9 +77,9 @@ func (r *ReferralRepo) GetReferralByCode(ctx context.Context, code string) (*dom
|
|||
}
|
||||
|
||||
func (r *ReferralRepo) UpdateReferral(ctx context.Context, referral *domain.Referral) error {
|
||||
var referredID pgtype.Text
|
||||
var referredID pgtype.Int8
|
||||
if referral.ReferredID != nil {
|
||||
referredID = pgtype.Text{String: *referral.ReferredID, Valid: true}
|
||||
referredID = pgtype.Int8{Int64: *referral.ReferredID, Valid: true}
|
||||
}
|
||||
|
||||
params := dbgen.UpdateReferralParams{
|
||||
|
|
@ -91,8 +92,11 @@ func (r *ReferralRepo) UpdateReferral(ctx context.Context, referral *domain.Refe
|
|||
return err
|
||||
}
|
||||
|
||||
func (r *ReferralRepo) GetReferralStats(ctx context.Context, userID string) (*domain.ReferralStats, error) {
|
||||
stats, err := r.store.queries.GetReferralStats(ctx, userID)
|
||||
func (r *ReferralRepo) GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error) {
|
||||
stats, err := r.store.queries.GetReferralStats(ctx, dbgen.GetReferralStatsParams{
|
||||
ReferrerID: userID,
|
||||
CompanyID: companyID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -175,8 +179,8 @@ func (r *ReferralRepo) CreateSettings(ctx context.Context, settings *domain.Refe
|
|||
return err
|
||||
}
|
||||
|
||||
func (r *ReferralRepo) GetReferralByReferredID(ctx context.Context, referredID string) (*domain.Referral, error) {
|
||||
dbReferral, err := r.store.queries.GetReferralByReferredID(ctx, pgtype.Text{String: referredID, Valid: true})
|
||||
func (r *ReferralRepo) GetReferralByReferredID(ctx context.Context, referredID int64) (*domain.Referral, error) {
|
||||
dbReferral, err := r.store.queries.GetReferralByReferredID(ctx, pgtype.Int8{Int64: referredID, Valid: true})
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
|
|
@ -186,7 +190,7 @@ func (r *ReferralRepo) GetReferralByReferredID(ctx context.Context, referredID s
|
|||
return r.mapToDomainReferral(&dbReferral), nil
|
||||
}
|
||||
|
||||
func (r *ReferralRepo) GetReferralCountByID(ctx context.Context, referrerID string) (int64, error) {
|
||||
func (r *ReferralRepo) GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error) {
|
||||
count, err := r.store.queries.GetReferralCountByID(ctx, referrerID)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
|
|
@ -198,7 +202,7 @@ func (r *ReferralRepo) GetReferralCountByID(ctx context.Context, referrerID stri
|
|||
return count, nil
|
||||
}
|
||||
|
||||
func (r *ReferralRepo) GetActiveReferralByReferrerID(ctx context.Context, referrerID string) (*domain.Referral, error) {
|
||||
func (r *ReferralRepo) GetActiveReferralByReferrerID(ctx context.Context, referrerID int64) (*domain.Referral, error) {
|
||||
referral, err := r.store.queries.GetActiveReferralByReferrerID(ctx, referrerID)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
|
|
@ -211,9 +215,9 @@ func (r *ReferralRepo) GetActiveReferralByReferrerID(ctx context.Context, referr
|
|||
}
|
||||
|
||||
func (r *ReferralRepo) mapToDomainReferral(dbRef *dbgen.Referral) *domain.Referral {
|
||||
var referredID *string
|
||||
var referredID *int64
|
||||
if dbRef.ReferredID.Valid {
|
||||
referredID = &dbRef.ReferredID.String
|
||||
referredID = &dbRef.ReferredID.Int64
|
||||
}
|
||||
|
||||
rewardAmount := 0.0
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ func (s *Store) GetUserByPhone(ctx context.Context, phoneNum string, companyID d
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64) error {
|
||||
func (s *Store) UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64, companyId int64) error {
|
||||
err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{
|
||||
ID: usedOtpId,
|
||||
UsedAt: pgtype.Timestamptz{
|
||||
|
|
@ -449,6 +449,10 @@ func (s *Store) UpdatePassword(ctx context.Context, identifier string, password
|
|||
String: identifier,
|
||||
Valid: true,
|
||||
},
|
||||
CompanyID: pgtype.Int8{
|
||||
Int64: companyId,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import (
|
|||
|
||||
type ReferralStore interface {
|
||||
GenerateReferralCode() (string, error)
|
||||
CreateReferral(ctx context.Context, userID int64) error
|
||||
CreateReferral(ctx context.Context, userID int64, companyID int64) error
|
||||
ProcessReferral(ctx context.Context, referredPhone, referralCode string, companyID int64) error
|
||||
ProcessDepositBonus(ctx context.Context, userID string, amount float64) error
|
||||
GetReferralStats(ctx context.Context, userID string) (*domain.ReferralStats, error)
|
||||
ProcessDepositBonus(ctx context.Context, userPhone string, amount float64) error
|
||||
ProcessBetReferral(ctx context.Context, userId int64, betAmount float64) error
|
||||
GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error)
|
||||
CreateReferralSettings(ctx context.Context, req domain.ReferralSettingsReq) error
|
||||
UpdateReferralSettings(ctx context.Context, settings *domain.ReferralSettings) error
|
||||
GetReferralSettings(ctx context.Context) (*domain.ReferralSettings, error)
|
||||
GetReferralCountByID(ctx context.Context, referrerID string) (int64, error)
|
||||
ProcessBetReferral(ctx context.Context, userPhone string, betAmount float64) error
|
||||
GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@ func (s *Service) GenerateReferralCode() (string, error) {
|
|||
return code, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateReferral(ctx context.Context, userID int64) error {
|
||||
func (s *Service) CreateReferral(ctx context.Context, userID int64, companyID int64) error {
|
||||
s.logger.Info("Creating referral code for user", "userID", userID)
|
||||
|
||||
// check if user already has an active referral code
|
||||
referral, err := s.repo.GetActiveReferralByReferrerID(ctx, fmt.Sprintf("%d", userID))
|
||||
referral, err := s.repo.GetActiveReferralByReferrerID(ctx, userID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to check if user alredy has active referral code", "error", err)
|
||||
return err
|
||||
|
|
@ -73,7 +73,7 @@ func (s *Service) CreateReferral(ctx context.Context, userID int64) error {
|
|||
}
|
||||
|
||||
// check referral count limit
|
||||
referralCount, err := s.GetReferralCountByID(ctx, fmt.Sprintf("%d", userID))
|
||||
referralCount, err := s.GetReferralCountByID(ctx, userID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referral count", "userID", userID, "error", err)
|
||||
return err
|
||||
|
|
@ -96,10 +96,11 @@ func (s *Service) CreateReferral(ctx context.Context, userID int64) error {
|
|||
|
||||
if err := s.repo.CreateReferral(ctx, &domain.Referral{
|
||||
ReferralCode: code,
|
||||
ReferrerID: fmt.Sprintf("%d", userID),
|
||||
ReferrerID: userID,
|
||||
Status: domain.ReferralPending,
|
||||
RewardAmount: rewardAmount,
|
||||
ExpiresAt: expireDuration,
|
||||
CompanyID: companyID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -138,7 +139,7 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
|
|||
return ErrInvalidReferralSignup
|
||||
}
|
||||
|
||||
referral.ReferredID = &referredPhone
|
||||
referral.ReferredID = &user.ID
|
||||
referral.Status = domain.ReferralCompleted
|
||||
referral.UpdatedAt = time.Now()
|
||||
|
||||
|
|
@ -147,13 +148,7 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
|
|||
return err
|
||||
}
|
||||
|
||||
referrerId, err := strconv.Atoi(referral.ReferrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to convert referrer id", "referrerId", referral.ReferrerID, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
wallets, err := s.store.GetCustomerWallet(ctx, int64(referrerId))
|
||||
wallets, err := s.store.GetCustomerWallet(ctx, referral.ReferrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referrer wallets", "referrerId", referral.ReferrerID, "error", err)
|
||||
return err
|
||||
|
|
@ -161,7 +156,7 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
|
|||
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallets.StaticID,
|
||||
domain.ToCurrency(float32(referral.RewardAmount)), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
||||
fmt.Sprintf("Added %v to static wallet because of referral ID %v", referral.RewardAmount, referrerId),
|
||||
fmt.Sprintf("Added %v to static wallet because of referral ID %v", referral.RewardAmount, referral.ReferrerID),
|
||||
)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to add referral reward to static wallet", "walletID", wallets.StaticID, "referrer phone number", referredPhone, "error", err)
|
||||
|
|
@ -212,8 +207,8 @@ func (s *Service) ProcessDepositBonus(ctx context.Context, userPhone string, amo
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessBetReferral(ctx context.Context, userPhone string, betAmount float64) error {
|
||||
s.logger.Info("Processing bet referral", "userPhone", userPhone, "betAmount", betAmount)
|
||||
func (s *Service) ProcessBetReferral(ctx context.Context, userId int64, betAmount float64) error {
|
||||
s.logger.Info("Processing bet referral", "userID", userId, "betAmount", betAmount)
|
||||
|
||||
settings, err := s.repo.GetSettings(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -221,29 +216,24 @@ func (s *Service) ProcessBetReferral(ctx context.Context, userPhone string, betA
|
|||
return err
|
||||
}
|
||||
|
||||
referral, err := s.repo.GetReferralByReferredID(ctx, userPhone)
|
||||
referral, err := s.repo.GetReferralByReferredID(ctx, userId)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referral by referred ID", "userPhone", userPhone, "error", err)
|
||||
s.logger.Error("Failed to get referral by referred ID", "userId", userId, "error", err)
|
||||
return err
|
||||
}
|
||||
if referral == nil || referral.Status != domain.ReferralCompleted {
|
||||
s.logger.Warn("No valid referral found", "userPhone", userPhone, "status", referral.Status)
|
||||
s.logger.Warn("No valid referral found", "userId", userId, "status", referral.Status)
|
||||
return ErrNoReferralFound
|
||||
}
|
||||
|
||||
referrerID, err := strconv.ParseInt(referral.ReferrerID, 10, 64)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid referrer phone number format", "referrerID", referral.ReferrerID, "error", err)
|
||||
return errors.New("invalid referrer phone number format")
|
||||
}
|
||||
|
||||
wallets, err := s.walletSvc.GetWalletsByUser(ctx, referrerID)
|
||||
wallets, err := s.walletSvc.GetWalletsByUser(ctx, referral.ReferrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get wallets for referrer", "referrerID", referrerID, "error", err)
|
||||
s.logger.Error("Failed to get wallets for referrer", "referrerID", referral.ReferrerID, "error", err)
|
||||
return err
|
||||
}
|
||||
if len(wallets) == 0 {
|
||||
s.logger.Error("Referrer has no wallet", "referrerID", referrerID)
|
||||
s.logger.Error("Referrer has no wallet", "referrerID", referral.ReferrerID)
|
||||
return errors.New("referrer has no wallet")
|
||||
}
|
||||
|
||||
|
|
@ -260,24 +250,24 @@ func (s *Service) ProcessBetReferral(ctx context.Context, userPhone string, betA
|
|||
domain.TRANSFER_DIRECT, domain.PaymentDetails{},
|
||||
fmt.Sprintf("Added %v to static wallet because of bet referral", referral.RewardAmount))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to add bet referral bonus to wallet", "walletID", walletID, "referrerID", referrerID, "bonus", bonus, "error", err)
|
||||
s.logger.Error("Failed to add bet referral bonus to wallet", "walletID", walletID, "referrerID", referral.ReferrerID, "bonus", bonus, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
s.logger.Info("Bet referral processed successfully", "userPhone", userPhone, "referrerID", referrerID, "bonus", bonus)
|
||||
s.logger.Info("Bet referral processed successfully", "referrer ID", referral.ReferrerID, "referrerID", referral.ReferrerID, "bonus", bonus)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetReferralStats(ctx context.Context, userPhone string) (*domain.ReferralStats, error) {
|
||||
s.logger.Info("Fetching referral stats", "userPhone", userPhone)
|
||||
func (s *Service) GetReferralStats(ctx context.Context, userID int64, companyID int64) (*domain.ReferralStats, error) {
|
||||
s.logger.Info("Fetching referral stats", "userID", userID)
|
||||
|
||||
stats, err := s.repo.GetReferralStats(ctx, userPhone)
|
||||
stats, err := s.repo.GetReferralStats(ctx, userID, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referral stats", "userPhone", userPhone, "error", err)
|
||||
s.logger.Error("Failed to get referral stats", "userID", userID, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.logger.Info("Referral stats retrieved successfully", "userPhone", userPhone, "totalReferrals", stats.TotalReferrals)
|
||||
s.logger.Info("Referral stats retrieved successfully", "userID", userID, "totalReferrals", stats.TotalReferrals)
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +318,7 @@ func (s *Service) GetReferralSettings(ctx context.Context) (*domain.ReferralSett
|
|||
return settings, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetReferralCountByID(ctx context.Context, referrerID string) (int64, error) {
|
||||
func (s *Service) GetReferralCountByID(ctx context.Context, referrerID int64) (int64, error) {
|
||||
count, err := s.repo.GetReferralCountByID(ctx, referrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referral count", "userID", referrerID, "error", err)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ type UserStore interface {
|
|||
GetUserByEmail(ctx context.Context, email string, companyID domain.ValidInt64) (domain.User, error)
|
||||
GetUserByPhone(ctx context.Context, phoneNum string, companyID domain.ValidInt64) (domain.User, error)
|
||||
SearchUserByNameOrPhone(ctx context.Context, searchString string, role *domain.Role, companyID domain.ValidInt64) ([]domain.User, error)
|
||||
UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64) error // identifier verified email or phone
|
||||
UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64, companyId int64) error
|
||||
|
||||
GetCustomerCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
GetCustomerDetails(ctx context.Context, filter domain.ReportFilter) (map[int64]domain.CustomerDetail, error)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (s *Service) ResetPassword(ctx context.Context, resetReq domain.ResetPasswo
|
|||
}
|
||||
// reset pass and mark otp as used
|
||||
|
||||
err = s.userStore.UpdatePassword(ctx, sentTo, hashedPassword, otp.ID)
|
||||
err = s.userStore.UpdatePassword(ctx, sentTo, hashedPassword, otp.ID, resetReq.CompanyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,10 +156,10 @@ func SetupReportandVirtualGameCronJobs(
|
|||
spec string
|
||||
period string
|
||||
}{
|
||||
{
|
||||
spec: "*/60 * * * * *", // Every 1 minute for testing
|
||||
period: "test",
|
||||
},
|
||||
// {
|
||||
// spec: "*/60 * * * * *", // Every 1 minute for testing
|
||||
// period: "test",
|
||||
// },
|
||||
{
|
||||
spec: "0 0 0 * * *", // Daily at midnight
|
||||
period: "daily",
|
||||
|
|
@ -254,8 +254,6 @@ func SetupReportandVirtualGameCronJobs(
|
|||
log.Printf("Cron jobs started. Reports will be saved to: %s", outputDir)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func ProcessBetCashback(ctx context.Context, betService *betSvc.Service) {
|
||||
c := cron.New(cron.WithSeconds())
|
||||
|
||||
|
|
|
|||
|
|
@ -196,11 +196,13 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
|||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
companyFilter := int64(c.QueryInt("company_id"))
|
||||
filter := domain.UserFilter{
|
||||
Role: string(domain.RoleAdmin),
|
||||
CompanyID: domain.ValidInt64{
|
||||
Value: int64(c.QueryInt("company_id")),
|
||||
Valid: false,
|
||||
Value: companyFilter,
|
||||
Valid: companyFilter != 0,
|
||||
},
|
||||
Page: domain.ValidInt{
|
||||
Value: c.QueryInt("page", 1) - 1,
|
||||
|
|
|
|||
|
|
@ -107,7 +107,13 @@ func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusForbidden, "Only customers are allowed to login ")
|
||||
}
|
||||
|
||||
accessToken, err := jwtutil.CreateJwt(successRes.UserId, successRes.Role, successRes.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
|
||||
accessToken, err := jwtutil.CreateJwt(
|
||||
successRes.UserId,
|
||||
successRes.Role,
|
||||
successRes.CompanyID,
|
||||
h.jwtConfig.JwtAccessKey,
|
||||
h.jwtConfig.JwtAccessExpiry,
|
||||
);
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to create access token",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
|
|
|
|||
|
|
@ -379,9 +379,110 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet [get]
|
||||
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
// companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
// branchID := c.Locals("branch_id").(domain.ValidInt64)
|
||||
|
||||
var isShopBet domain.ValidBool
|
||||
isShopBetQuery := c.Query("is_shop")
|
||||
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
||||
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("failed to parse is_shop_bet",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("is_shop", isShopBetQuery),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to parse is_shop_bet")
|
||||
}
|
||||
isShopBet = domain.ValidBool{
|
||||
Value: isShopBetParse,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
createdBeforeQuery := c.Query("created_before")
|
||||
var createdBefore domain.ValidTime
|
||||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("time", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
createdAfterQuery := c.Query("created_after")
|
||||
var createdAfter domain.ValidTime
|
||||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("created_after", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
|
||||
IsShopBet: isShopBet,
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get all bets",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets፡"+err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.BetRes, len(bets))
|
||||
for i, bet := range bets {
|
||||
res[i] = domain.ConvertBet(bet)
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All bets retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetAllTenants godoc
|
||||
// @Summary Gets all bets
|
||||
// @Description Gets all the bets
|
||||
// @Tags bet
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet [get]
|
||||
func (h *Handler) GetAllTenantBets(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
h.BadRequestLogger().Error("invalid company id", zap.Any("company_id", companyID))
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
role := c.Locals("role").(domain.Role)
|
||||
|
|
@ -485,8 +586,54 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [get]
|
||||
// @Router /api/v1/sport/bet/{id} [get]
|
||||
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
||||
betID := c.Params("id")
|
||||
id, err := strconv.ParseInt(betID, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Invalid bet ID",
|
||||
zap.String("betID", betID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
||||
}
|
||||
|
||||
bet, err := h.betSvc.GetBetByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to get bet by ID",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusNotFound),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
|
||||
}
|
||||
|
||||
res := domain.ConvertBet(bet)
|
||||
|
||||
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
|
||||
// zap.Int64("betID", id),
|
||||
// zap.Int("status_code", fiber.StatusOK),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetTenantBetByID godoc
|
||||
// @Summary Gets bet by id
|
||||
// @Description Gets a single bet by id
|
||||
// @Tags bet
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Bet ID"
|
||||
// @Success 200 {object} domain.BetRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [get]
|
||||
func (h *Handler) GetTenantBetByID(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
|
|
@ -696,8 +843,52 @@ func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [delete]
|
||||
// @Router /api/v1/sport/bet/{id} [delete]
|
||||
func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
||||
betID := c.Params("id")
|
||||
id, err := strconv.ParseInt(betID, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid bet ID",
|
||||
zap.String("betID", betID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
||||
}
|
||||
|
||||
err = h.betSvc.SetBetToRemoved(c.Context(), id)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to delete bet by ID",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete bet:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("Bet removed successfully",
|
||||
zap.Int64("betID", id),
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bet removed successfully", nil, nil)
|
||||
}
|
||||
|
||||
// DeleteTenantBet godoc
|
||||
// @Summary Deletes bet by id
|
||||
// @Description Deletes bet by id
|
||||
// @Tags bet
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Bet ID"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [delete]
|
||||
func (h *Handler) DeleteTenantBet(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ func (h *Handler) CreateBranchOperation(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil)
|
||||
}
|
||||
|
||||
|
||||
// GetBranchByID godoc
|
||||
// @Summary Gets branch by id
|
||||
// @Description Gets a single branch by id
|
||||
|
|
@ -295,6 +296,108 @@ func (h *Handler) GetBranchByID(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Branch retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// ReturnBranchWallet godoc
|
||||
// @Summary Unassign the branch wallet to company
|
||||
// @Description Unassign the branch wallet to company
|
||||
// @Tags branch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Branch ID"
|
||||
// @Success 200 {object} domain.BranchDetailRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/branch/{id}/return [post]
|
||||
func (h *Handler) ReturnBranchWallet(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
||||
branchID := c.Params("id")
|
||||
id, err := strconv.ParseInt(branchID, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Invalid branch ID",
|
||||
zap.String("branch", branchID),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
|
||||
}
|
||||
|
||||
branch, err := h.branchSvc.GetBranchByID(c.Context(), id)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to get branch by ID",
|
||||
zap.Int64("branchID", id),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), branch.CompanyID)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to get company by ID",
|
||||
zap.Int64("branchID", id),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
branchWallet, err := h.walletSvc.GetWalletByID(c.Context(), branch.WalletID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to get wallet by ID",
|
||||
zap.Int64("branchID", id),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
_, err = h.walletSvc.AddToWallet(c.Context(),
|
||||
company.WalletID,
|
||||
branchWallet.Balance,
|
||||
domain.ValidInt64{Value: userID, Valid: true},
|
||||
domain.TRANSFER_DIRECT,
|
||||
domain.PaymentDetails{},
|
||||
fmt.Sprintf("Returning Branch %v Wallet to Company", branch.Name))
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to add to company wallet",
|
||||
zap.Int64("branchID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
_, err = h.walletSvc.DeductFromWallet(c.Context(),
|
||||
branchWallet.ID,
|
||||
branchWallet.Balance,
|
||||
domain.ValidInt64{Value: userID, Valid: true},
|
||||
domain.TRANSFER_DIRECT,
|
||||
"Branch Wallet Balance has been returned to Company",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to deduct from branch wallet",
|
||||
zap.Int64("branchID", id),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
res := domain.ConvertBranchDetail(branch)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Branch Wallet Has been emptied", res, nil)
|
||||
}
|
||||
|
||||
// GetBranchByManagerID godoc
|
||||
// @Summary Gets branches by manager id
|
||||
// @Description Gets a branches by manager id
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ type CustomersRes struct {
|
|||
LastLogin time.Time `json:"last_login"`
|
||||
SuspendedAt time.Time `json:"suspended_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
CompanyID int64 `json:"company_id"`
|
||||
CompanyName string `json:"company_name"`
|
||||
}
|
||||
|
||||
// GetAllCustomers godoc
|
||||
|
|
@ -156,6 +158,30 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
"Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !customer.CompanyID.Valid {
|
||||
h.mongoLoggerSvc.Error("Invalid user company ID",
|
||||
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 company id for customer:")
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), customer.CompanyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid user company value",
|
||||
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 fetch company for customer:")
|
||||
}
|
||||
result[index] = CustomersRes{
|
||||
ID: customer.ID,
|
||||
FirstName: customer.FirstName,
|
||||
|
|
@ -170,6 +196,176 @@ func (h *Handler) GetAllCustomers(c *fiber.Ctx) error {
|
|||
SuspendedAt: customer.SuspendedAt,
|
||||
Suspended: customer.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
CompanyID: company.ID,
|
||||
CompanyName: company.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Customers retrieved successfully", result, nil, filter.Page.Value, int(total))
|
||||
|
||||
}
|
||||
|
||||
// GetAllTenantCustomers godoc
|
||||
// @Summary Get all Customers
|
||||
// @Description Get all Customers
|
||||
// @Tags customer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "Page number"
|
||||
// @Param page_size query int false "Page size"
|
||||
// @Success 200 {object} CustomersRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/customer [get]
|
||||
func (h *Handler) GetAllTenantCustomers(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
createdBeforeQuery := c.Query("created_before")
|
||||
var createdBefore domain.ValidTime
|
||||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("invalid created_before format",
|
||||
zap.String("createdBefore", createdBeforeQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
createdAfterQuery := c.Query("created_after")
|
||||
var createdAfter domain.ValidTime
|
||||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("invalid created_after format",
|
||||
zap.String("createdAfter", createdAfterQuery),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
filter := domain.UserFilter{
|
||||
Role: string(domain.RoleCustomer),
|
||||
CompanyID: companyID,
|
||||
Page: domain.ValidInt{
|
||||
Value: c.QueryInt("page", 1) - 1,
|
||||
Valid: true,
|
||||
},
|
||||
PageSize: domain.ValidInt{
|
||||
Value: c.QueryInt("page_size", 10),
|
||||
Valid: true,
|
||||
},
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate GetAllCustomer filters",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("errMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
customers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("GetAllCustomers failed to get all users",
|
||||
zap.Any("filter", filter),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get Customers:"+err.Error())
|
||||
}
|
||||
|
||||
var result []CustomersRes = make([]CustomersRes, len(customers))
|
||||
for index, customer := range customers {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), customer.ID)
|
||||
if err != nil {
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &customer.CreatedAt
|
||||
} else {
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", customer.ID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError,
|
||||
"Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !customer.CompanyID.Valid {
|
||||
h.mongoLoggerSvc.Error("Invalid user company ID",
|
||||
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 company id for customer:")
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), customer.CompanyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid user company value",
|
||||
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 fetch company for customer:")
|
||||
}
|
||||
result[index] = CustomersRes{
|
||||
ID: customer.ID,
|
||||
FirstName: customer.FirstName,
|
||||
LastName: customer.LastName,
|
||||
Email: customer.Email,
|
||||
PhoneNumber: customer.PhoneNumber,
|
||||
Role: customer.Role,
|
||||
EmailVerified: customer.EmailVerified,
|
||||
PhoneVerified: customer.PhoneVerified,
|
||||
CreatedAt: customer.CreatedAt,
|
||||
UpdatedAt: customer.UpdatedAt,
|
||||
SuspendedAt: customer.SuspendedAt,
|
||||
Suspended: customer.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
CompanyID: company.ID,
|
||||
CompanyName: company.Name,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +418,29 @@ func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
|
|||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
||||
if !user.CompanyID.Valid {
|
||||
h.mongoLoggerSvc.Error("Invalid user company ID",
|
||||
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 company id for customer:")
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), user.CompanyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid user company value",
|
||||
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 fetch company for customer:")
|
||||
}
|
||||
res := CustomersRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
|
|
@ -236,16 +455,226 @@ func (h *Handler) GetCustomerByID(c *fiber.Ctx) error {
|
|||
SuspendedAt: user.SuspendedAt,
|
||||
Suspended: user.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
CompanyID: company.ID,
|
||||
CompanyName: company.Name,
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetCustomerByID godoc
|
||||
// @Summary Get customer by id
|
||||
// @Description Get a single customer by id
|
||||
// @Tags customer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} CustomersRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/customer/{id} [get]
|
||||
func (h *Handler) GetTenantCustomerByID(c *fiber.Ctx) error {
|
||||
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid customers ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get customers",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get customers:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.mongoLoggerSvc.Error("Failed to get user last login",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
||||
if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value {
|
||||
h.mongoLoggerSvc.Error("Failed to get customer",
|
||||
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 customer:"+err.Error())
|
||||
}
|
||||
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), user.CompanyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Invalid user company value",
|
||||
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 fetch company for customer:")
|
||||
}
|
||||
res := CustomersRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email,
|
||||
PhoneNumber: user.PhoneNumber,
|
||||
Role: user.Role,
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
SuspendedAt: user.SuspendedAt,
|
||||
Suspended: user.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
CompanyID: company.ID,
|
||||
CompanyName: company.Name,
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetTenantCustomerBets godoc
|
||||
// @Summary Get tenant customer bets
|
||||
// @Description Get tenant customer bets
|
||||
// @Tags customer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} CustomersRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/customer/{id}/bets [get]
|
||||
func (h *Handler) GetTenantCustomerBets(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid customers ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
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())
|
||||
}
|
||||
|
||||
if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value {
|
||||
h.mongoLoggerSvc.Warn("User Attempt to access another companies customer",
|
||||
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 customer bet")
|
||||
}
|
||||
|
||||
bets, err := h.betSvc.GetBetByUserID(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get user 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 get user bet:"+err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.BetRes, len(bets))
|
||||
for i, bet := range bets {
|
||||
res[i] = domain.ConvertBet(bet)
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User's Bets retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetCustomerBets godoc
|
||||
// @Summary Get customer bets
|
||||
// @Description Get customer bets
|
||||
// @Tags customer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} CustomersRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/customer/{id}/bets [get]
|
||||
func (h *Handler) GetCustomerBets(c *fiber.Ctx) error {
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid customers ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
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())
|
||||
}
|
||||
|
||||
bets, err := h.betSvc.GetBetByUserID(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get user 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 get user bet:"+err.Error())
|
||||
}
|
||||
|
||||
res := make([]domain.BetRes, len(bets))
|
||||
for i, bet := range bets {
|
||||
res[i] = domain.ConvertBet(bet)
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User's Bets retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
type updateCustomerReq struct {
|
||||
FirstName string `json:"first_name" example:"John"`
|
||||
LastName string `json:"last_name" example:"Doe"`
|
||||
Suspended bool `json:"suspended" example:"false"`
|
||||
CompanyID *int64 `json:"company_id,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
// UpdateCustomers godoc
|
||||
|
|
@ -341,3 +770,108 @@ func (h *Handler) UpdateCustomer(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Customers updated successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
// UpdateTenantCustomer godoc
|
||||
// @Summary Update Customers
|
||||
// @Description Update Customers
|
||||
// @Tags customer
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Customers body updateCustomerReq true "Update Customers"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/tenant/{tenant_slug}/customer/{id} [put]
|
||||
func (h *Handler) UpdateTenantCustomer(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
var req updateCustomerReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateCustomers invalid request body",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("Failed to validate UpdateCustomerReq",
|
||||
zap.Any("request", req),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("ErrMsg", errMsg),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
CustomersIdStr := c.Params("id")
|
||||
CustomersId, err := strconv.ParseInt(CustomersIdStr, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Invalid Customers ID",
|
||||
zap.String("userID", CustomersIdStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Customers ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), CustomersId)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("Customers Not Found",
|
||||
zap.String("userID", CustomersIdStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Customers Not Found")
|
||||
}
|
||||
|
||||
if user.CompanyID.Value != companyID.Value {
|
||||
h.mongoLoggerSvc.Warn("User Attempt to update another companies customer",
|
||||
zap.String("userID", CustomersIdStr),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Customers Not Found")
|
||||
}
|
||||
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
|
||||
UserId: CustomersId,
|
||||
FirstName: domain.ValidString{
|
||||
Value: req.FirstName,
|
||||
Valid: req.FirstName != "",
|
||||
},
|
||||
LastName: domain.ValidString{
|
||||
Value: req.LastName,
|
||||
Valid: req.LastName != "",
|
||||
},
|
||||
Suspended: domain.ValidBool{
|
||||
Value: req.Suspended,
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to update Customers",
|
||||
zap.Int64("userID", CustomersId),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update Customers:"+err.Error())
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Customers updated successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ import (
|
|||
)
|
||||
|
||||
func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.mongoLoggerSvc.Info("Invalid user ID in context",
|
||||
|
|
@ -21,7 +26,7 @@ func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
|||
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, companyID.Value); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to create referral",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
|
|
@ -35,6 +40,7 @@ func (h *Handler) CreateReferralCode(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
||||
|
||||
var req domain.ReferralSettingsReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to parse settings",
|
||||
|
|
@ -91,6 +97,57 @@ func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Referral created successfully", nil, nil)
|
||||
}
|
||||
|
||||
// func (h *Handler) GetReferralCode(c *fiber.Ctx) error {
|
||||
// companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
// if !companyID.Valid {
|
||||
// h.BadRequestLogger().Error("invalid company id")
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
// }
|
||||
// userID, ok := c.Locals("user_id").(int64)
|
||||
// if !ok || userID == 0 {
|
||||
// h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
// zap.Int64("userID", userID),
|
||||
// zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusInternalServerError, "Invalid user id")
|
||||
// }
|
||||
|
||||
// user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
// if err != nil {
|
||||
// h.mongoLoggerSvc.Error("Failed to get user",
|
||||
// zap.Int64("userID", userID),
|
||||
// zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
// }
|
||||
|
||||
// if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value {
|
||||
// h.mongoLoggerSvc.Warn("User attempt to login to different company",
|
||||
// zap.Int64("userID", userID),
|
||||
// zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
// zap.Error(err),
|
||||
// zap.Time("timestamp", time.Now()),
|
||||
// )
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "Failed to retrieve user")
|
||||
// }
|
||||
|
||||
// // referrals, err := h.referralSvc.GetReferralStats(c.Context(), user.ID)
|
||||
|
||||
// if err != nil {
|
||||
// h.mongoLoggerSvc.Error("Failed to get user referrals",
|
||||
// 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 referral codes")
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// GetReferralStats godoc
|
||||
// @Summary Get referral statistics
|
||||
// @Description Retrieves referral statistics for the authenticated user
|
||||
|
|
@ -101,8 +158,13 @@ func (h *Handler) CreateReferralSettings(c *fiber.Ctx) error {
|
|||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Security Bearer
|
||||
// @Router /api/v1/referral/stats [get]
|
||||
// @Router /api/v1/tenant/{tenant_slug}/referral/stats [get]
|
||||
func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
h.mongoLoggerSvc.Error("Invalid user ID in context",
|
||||
|
|
@ -124,7 +186,17 @@ func (h *Handler) GetReferralStats(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
}
|
||||
|
||||
stats, err := h.referralSvc.GetReferralStats(c.Context(), user.PhoneNumber)
|
||||
if !user.CompanyID.Valid || user.CompanyID.Value != companyID.Value {
|
||||
h.mongoLoggerSvc.Warn("User attempt to login to different company",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to retrieve user")
|
||||
}
|
||||
|
||||
stats, err := h.referralSvc.GetReferralStats(c.Context(), user.ID, companyID.Value)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get referral stats",
|
||||
zap.Int64("userID", userID),
|
||||
|
|
@ -227,33 +299,9 @@ func (h *Handler) GetReferralSettings(c *fiber.Ctx) error {
|
|||
// h.logger.Error("Invalid user ID in context")
|
||||
// return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
||||
// }
|
||||
userID := int64(2)
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get user",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user")
|
||||
}
|
||||
|
||||
if user.Role != domain.RoleAdmin {
|
||||
h.mongoLoggerSvc.Error("Admin access required",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusForbidden),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusForbidden, "Admin access required")
|
||||
}
|
||||
|
||||
settings, err := h.referralSvc.GetReferralSettings(c.Context())
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get referral settings",
|
||||
zap.Int64("userID", userID),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
|
|
|
|||
438
internal/web_server/handlers/transaction_approver.go
Normal file
438
internal/web_server/handlers/transaction_approver.go
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CreateTransactionApproverReq struct {
|
||||
FirstName string `json:"first_name" example:"John"`
|
||||
LastName string `json:"last_name" example:"Doe"`
|
||||
Email string `json:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
Password string `json:"password" example:"password123"`
|
||||
CompanyID int64 `json:"company_id" example:"1"`
|
||||
}
|
||||
|
||||
// CreateTransactionApprover godoc
|
||||
// @Summary Create transaction approver
|
||||
// @Description Create transaction approver
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param manger body CreateTransactionApproverReq true "Create transaction approver"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/admin [post]
|
||||
func (h *Handler) CreateTransactionApprover(c *fiber.Ctx) error {
|
||||
var companyID domain.ValidInt64
|
||||
var req CreateTransactionApproverReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Info("failed to parse CreateAdmin request",
|
||||
zap.Int64("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request:"+err.Error())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Error("validation failed for CreateAdmin request",
|
||||
zap.Int64("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
_, err := h.companySvc.GetCompanyByID(c.Context(), req.CompanyID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid company ID for CreateAdmin",
|
||||
zap.Int64("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("company_id", req.CompanyID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Company ID is invalid:"+err.Error())
|
||||
}
|
||||
companyID = domain.ValidInt64{
|
||||
Value: req.CompanyID,
|
||||
Valid: true,
|
||||
}
|
||||
|
||||
user := domain.CreateUserReq{
|
||||
FirstName: req.FirstName,
|
||||
LastName: req.LastName,
|
||||
Email: req.Email,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
Password: req.Password,
|
||||
Role: string(domain.RoleTransactionApprover),
|
||||
CompanyID: companyID,
|
||||
}
|
||||
|
||||
newUser, err := h.userSvc.CreateUser(c.Context(), user, true)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to create admin user",
|
||||
zap.Int64("status_code", fiber.StatusInternalServerError),
|
||||
zap.Any("request", req),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create admin:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("transaction_approver created successfully",
|
||||
zap.Int64("transaction_approver_id", newUser.ID),
|
||||
zap.String("email", newUser.Email),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Transaction Approver created successfully", nil, nil)
|
||||
}
|
||||
|
||||
type TransactionApproverRes struct {
|
||||
ID int64 `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Email string `json:"email"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
Role domain.Role `json:"role"`
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
LastLogin time.Time `json:"last_login"`
|
||||
SuspendedAt time.Time `json:"suspended_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
}
|
||||
|
||||
// GetAllAdmins godoc
|
||||
// @Summary Get all Admins
|
||||
// @Description Get all Admins
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "Page number"
|
||||
// @Param page_size query int false "Page size"
|
||||
// @Success 200 {object} AdminRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/t-approver [get]
|
||||
func (h *Handler) GetAllTransactionApprovers(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
createdBeforeQuery := c.Query("created_before")
|
||||
var createdBefore domain.ValidTime
|
||||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Info("invalid start_time format", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
createdAfterQuery := c.Query("created_after")
|
||||
var createdAfter domain.ValidTime
|
||||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Info("invalid start_time format", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
var companyIDFilter domain.ValidInt64
|
||||
if role == domain.RoleSuperAdmin {
|
||||
companyIDQuery := int64(c.QueryInt("company_id"))
|
||||
companyIDFilter = domain.ValidInt64{
|
||||
Value: companyIDQuery,
|
||||
Valid: companyIDQuery != 0,
|
||||
}
|
||||
} else {
|
||||
if !companyID.Valid {
|
||||
h.logger.Info("invalid companyID")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Unable to get company ID")
|
||||
}
|
||||
|
||||
companyIDFilter = companyID
|
||||
}
|
||||
|
||||
filter := domain.UserFilter{
|
||||
Role: string(domain.RoleTransactionApprover),
|
||||
CompanyID: companyIDFilter,
|
||||
Page: domain.ValidInt{
|
||||
Value: c.QueryInt("page", 1) - 1,
|
||||
Valid: true,
|
||||
},
|
||||
PageSize: domain.ValidInt{
|
||||
Value: c.QueryInt("page_size", 10),
|
||||
Valid: true,
|
||||
},
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Info("invalid filter values in GetAllAdmins request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
users, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to get users from user service",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Any("filter", filter),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get users"+err.Error())
|
||||
}
|
||||
|
||||
result := make([]TransactionApproverRes, len(users))
|
||||
for index, admin := range users {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), admin.ID)
|
||||
if err != nil {
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &admin.CreatedAt
|
||||
} else {
|
||||
h.mongoLoggerSvc.Error("failed to get last login for admin",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("admin_id", admin.ID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
result[index] = TransactionApproverRes{
|
||||
ID: admin.ID,
|
||||
FirstName: admin.FirstName,
|
||||
LastName: admin.LastName,
|
||||
Email: admin.Email,
|
||||
PhoneNumber: admin.PhoneNumber,
|
||||
Role: admin.Role,
|
||||
EmailVerified: admin.EmailVerified,
|
||||
PhoneVerified: admin.PhoneVerified,
|
||||
CreatedAt: admin.CreatedAt,
|
||||
UpdatedAt: admin.UpdatedAt,
|
||||
SuspendedAt: admin.SuspendedAt,
|
||||
Suspended: admin.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
}
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("approvers retrieved successfully",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int("count", len(result)),
|
||||
zap.Int("page", filter.Page.Value+1),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value, int(total))
|
||||
}
|
||||
|
||||
// GetAdminByID godoc
|
||||
// @Summary Get admin by id
|
||||
// @Description Get a single admin by id
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} AdminRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/t-approver/{id} [get]
|
||||
func (h *Handler) GetTransactionApproverByID(c *fiber.Ctx) error {
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("invalid admin ID param",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("param", userIDstr),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid admin ID")
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("failed to fetch admin by ID",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("admin_id", userID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get admin"+err.Error())
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil && err != authentication.ErrRefreshTokenNotFound {
|
||||
h.mongoLoggerSvc.Error("failed to get admin last login",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
|
||||
}
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
||||
res := TransactionApproverRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email,
|
||||
PhoneNumber: user.PhoneNumber,
|
||||
Role: user.Role,
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
SuspendedAt: user.SuspendedAt,
|
||||
Suspended: user.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("admin retrieved successfully",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int64("admin_id", user.ID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Admin retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
type updateTransactionApproverReq struct {
|
||||
FirstName string `json:"first_name" example:"John"`
|
||||
LastName string `json:"last_name" example:"Doe"`
|
||||
Suspended bool `json:"suspended" example:"false"`
|
||||
}
|
||||
|
||||
// UpdateAdmin godoc
|
||||
// @Summary Update Admin
|
||||
// @Description Update Admin
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param admin body updateAdminReq true "Update Admin"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/t-approver/{id} [put]
|
||||
func (h *Handler) UpdateTransactionApprover(c *fiber.Ctx) error {
|
||||
var req updateTransactionApproverReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - 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())
|
||||
}
|
||||
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - validation errors",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Any("validation_errors", valErrs),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
ApproverIDStr := c.Params("id")
|
||||
ApproverID, err := strconv.ParseInt(ApproverIDStr, 10, 64)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Info("UpdateAdmin failed - invalid Admin ID param",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.String("admin_id_param", ApproverIDStr),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Admin ID")
|
||||
}
|
||||
|
||||
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
|
||||
UserId: ApproverID,
|
||||
FirstName: domain.ValidString{
|
||||
Value: req.FirstName,
|
||||
Valid: req.FirstName != "",
|
||||
},
|
||||
LastName: domain.ValidString{
|
||||
Value: req.LastName,
|
||||
Valid: req.LastName != "",
|
||||
},
|
||||
Suspended: domain.ValidBool{
|
||||
Value: req.Suspended,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("UpdateAdmin failed - user service error",
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Int64("admin_id", ApproverID),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update admin:"+err.Error())
|
||||
}
|
||||
|
||||
h.mongoLoggerSvc.Info("UpdateAdmin succeeded",
|
||||
zap.Int("status_code", fiber.StatusOK),
|
||||
zap.Int64("admin_id", ApproverID),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Managers updated successfully", nil, nil)
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ type RegisterUserReq struct {
|
|||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
Password string `json:"password" example:"password123"`
|
||||
Otp string `json:"otp" example:"123456"`
|
||||
ReferalCode string `json:"referal_code" example:"ABC123"`
|
||||
ReferralCode string `json:"referral_code" example:"ABC123"`
|
||||
}
|
||||
|
||||
// RegisterUser godoc
|
||||
|
|
@ -193,7 +193,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
PhoneNumber: req.PhoneNumber,
|
||||
Password: req.Password,
|
||||
Otp: req.Otp,
|
||||
ReferralCode: req.ReferalCode,
|
||||
ReferralCode: req.ReferralCode,
|
||||
OtpMedium: domain.OtpMediumEmail,
|
||||
CompanyID: companyID,
|
||||
Role: string(domain.RoleCustomer),
|
||||
|
|
@ -247,12 +247,12 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet:"+err.Error())
|
||||
}
|
||||
|
||||
if req.ReferalCode != "" {
|
||||
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferalCode, companyID.Value)
|
||||
if req.ReferralCode != "" {
|
||||
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferralCode, companyID.Value)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to process referral during registration",
|
||||
zap.String("phone", req.PhoneNumber),
|
||||
zap.String("code", req.ReferalCode),
|
||||
zap.String("code", req.ReferralCode),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
|
|
@ -293,8 +293,70 @@ type ResetCodeReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/user/sendResetCode [post]
|
||||
// @Router /api/v1/user/sendResetCode [post]
|
||||
func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
||||
var req ResetCodeReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to parse SendResetCode request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
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 medium domain.OtpMedium
|
||||
if req.Email != "" {
|
||||
sentTo = req.Email
|
||||
medium = domain.OtpMediumEmail
|
||||
} else if req.PhoneNumber != "" {
|
||||
sentTo = req.PhoneNumber
|
||||
medium = domain.OtpMediumSms
|
||||
} else {
|
||||
h.mongoLoggerSvc.Info("Email or PhoneNumber must be provided",
|
||||
zap.String("Email", req.Email),
|
||||
zap.String("Phone Number", req.PhoneNumber),
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
||||
}
|
||||
|
||||
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, domain.AfroMessage, domain.ValidInt64{}); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to send reset code",
|
||||
zap.String("medium", string(medium)),
|
||||
zap.String("sentTo", string(sentTo)),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||
}
|
||||
|
||||
// SendTenantResetCode godoc
|
||||
// @Summary Send reset code
|
||||
// @Description Send reset code
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param resetCode body ResetCodeReq true "Send reset code"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/user/sendResetCode [post]
|
||||
func (h *Handler) SendTenantResetCode(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
|
|
@ -367,7 +429,7 @@ type ResetPasswordReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/user/resetPassword [post]
|
||||
// @Router /api/v1/user/resetPassword [post]
|
||||
func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
||||
|
||||
var req ResetPasswordReq
|
||||
|
|
@ -421,6 +483,76 @@ func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
|
||||
}
|
||||
|
||||
// ResetTenantPassword godoc
|
||||
// @Summary Reset tenant password
|
||||
// @Description Reset tenant password
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param resetPassword body ResetPasswordReq true "Reset password"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /api/v1/{tenant_slug}/user/resetPassword [post]
|
||||
func (h *Handler) ResetTenantPassword(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
var req ResetPasswordReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.mongoLoggerSvc.Info("Failed to parse ResetPassword request",
|
||||
zap.Int("status_code", fiber.StatusBadRequest),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
||||
}
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
var errMsg string
|
||||
for field, msg := range valErrs {
|
||||
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, errMsg)
|
||||
}
|
||||
|
||||
medium, err := getMedium(req.Email, req.PhoneNumber)
|
||||
if err != nil {
|
||||
h.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())
|
||||
}
|
||||
|
||||
resetReq := domain.ResetPasswordReq{
|
||||
Email: req.Email,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
Password: req.Password,
|
||||
Otp: req.Otp,
|
||||
OtpMedium: medium,
|
||||
CompanyID: companyID.Value,
|
||||
}
|
||||
|
||||
if err := h.userSvc.ResetPassword(c.Context(), resetReq); err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to reset password",
|
||||
zap.Any("userID", resetReq),
|
||||
zap.Int("status_code", fiber.StatusInternalServerError),
|
||||
zap.Error(err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset password:"+err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
|
||||
}
|
||||
|
||||
type UserProfileRes struct {
|
||||
ID int64 `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
|
|
@ -503,6 +635,7 @@ func (h *Handler) CustomerProfile(c *fiber.Ctx) error {
|
|||
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
||||
res := CustomerProfileRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package jwtutil
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
|
|
@ -15,11 +16,12 @@ var (
|
|||
ErrRefreshTokenNotFound = errors.New("refresh token not found")
|
||||
)
|
||||
|
||||
|
||||
type UserClaim struct {
|
||||
jwt.RegisteredClaims
|
||||
UserId int64
|
||||
Role domain.Role
|
||||
CompanyID domain.ValidInt64
|
||||
CompanyID domain.NullJwtInt64
|
||||
}
|
||||
|
||||
type PopOKClaim struct {
|
||||
|
|
@ -30,7 +32,7 @@ type PopOKClaim struct {
|
|||
Lang string `json:"lang"`
|
||||
Mode string `json:"mode"`
|
||||
SessionID string `json:"session_id"`
|
||||
CompanyID domain.ValidInt64 `json:"company_id"`
|
||||
CompanyID domain.NullJwtInt64 `json:"company_id"`
|
||||
}
|
||||
|
||||
type JwtConfig struct {
|
||||
|
|
@ -41,15 +43,18 @@ type JwtConfig struct {
|
|||
func CreateJwt(userId int64, Role domain.Role, CompanyID domain.ValidInt64, key string, expiry int) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Issuer: "github.com/lafetz/snippitstash",
|
||||
Issuer: "fortune-bet",
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
Audience: jwt.ClaimStrings{"fortune.com"},
|
||||
Audience: jwt.ClaimStrings{"api.fortunebets.net"},
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiry) * time.Second)),
|
||||
},
|
||||
UserId: userId,
|
||||
Role: Role,
|
||||
CompanyID: CompanyID,
|
||||
CompanyID: domain.NullJwtInt64{
|
||||
Value: CompanyID.Value,
|
||||
Valid: CompanyID.Valid,
|
||||
},
|
||||
})
|
||||
jwtToken, err := token.SignedString([]byte(key))
|
||||
return jwtToken, err
|
||||
|
|
@ -70,7 +75,10 @@ func CreatePopOKJwt(userID int64, CompanyID domain.ValidInt64, username, currenc
|
|||
Lang: lang,
|
||||
Mode: mode,
|
||||
SessionID: sessionID,
|
||||
CompanyID: CompanyID,
|
||||
CompanyID: domain.NullJwtInt64{
|
||||
Value: CompanyID.Value,
|
||||
Valid: CompanyID.Valid,
|
||||
},
|
||||
})
|
||||
return token.SignedString([]byte(key))
|
||||
}
|
||||
|
|
@ -84,6 +92,7 @@ func ParseJwt(jwtToken string, key string) (*UserClaim, error) {
|
|||
return nil, ErrExpiredToken
|
||||
}
|
||||
if errors.Is(err, jwt.ErrTokenMalformed) {
|
||||
fmt.Printf("error %v", err.Error())
|
||||
return nil, ErrMalformedToken
|
||||
}
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package httpserver
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid access token")
|
||||
}
|
||||
|
|
@ -79,7 +81,10 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
}
|
||||
c.Locals("user_id", claim.UserId)
|
||||
c.Locals("role", claim.Role)
|
||||
c.Locals("company_id", claim.CompanyID)
|
||||
c.Locals("company_id", domain.ValidInt64{
|
||||
Value: claim.CompanyID.Value,
|
||||
Valid: claim.CompanyID.Valid,
|
||||
})
|
||||
c.Locals("refresh_token", refreshToken)
|
||||
|
||||
var branchID domain.ValidInt64
|
||||
|
|
@ -198,6 +203,7 @@ func (a *App) WebsocketAuthMiddleware(c *fiber.Ctx) error {
|
|||
zap.String("ip_address", ip),
|
||||
zap.String("user_agent", userAgent),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid token")
|
||||
}
|
||||
|
|
@ -222,17 +228,20 @@ func (a *App) WebsocketAuthMiddleware(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
func (a *App) TenantMiddleware(c *fiber.Ctx) error {
|
||||
if tokenCID, ok := c.Locals("company_id").(domain.ValidInt64); ok && tokenCID.Valid {
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
tenantSlug := c.Params("tenant_slug")
|
||||
if tenantSlug == "" {
|
||||
a.mongoLoggerSvc.Info("blank tenant param",
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "tenant is required for this route")
|
||||
}
|
||||
|
||||
companyID, err := a.companySvc.GetCompanyIDBySlug(c.Context(), tenantSlug)
|
||||
if err != nil {
|
||||
a.mongoLoggerSvc.Info("failed to resolve tenant",
|
||||
zap.String("tenant_slug", tenantSlug),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "failed to resolve tenant")
|
||||
}
|
||||
|
||||
|
|
@ -242,3 +251,35 @@ func (a *App) TenantMiddleware(c *fiber.Ctx) error {
|
|||
})
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func (a *App) TenantAuthMiddleware(c *fiber.Ctx) error {
|
||||
slugID, ok := c.Locals("tenant_id").(domain.ValidInt64)
|
||||
|
||||
if !ok || !slugID.Valid {
|
||||
a.mongoLoggerSvc.Info("invalid tenant slug",
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid tenant slug")
|
||||
}
|
||||
|
||||
tokenCID, ok := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !ok || !tokenCID.Valid {
|
||||
a.mongoLoggerSvc.Error("invalid company id in token",
|
||||
zap.Time("timestamp", time.Now()),
|
||||
zap.Bool("tokenCID Valid", tokenCID.Valid),
|
||||
zap.Bool("ValidInt64 Type Check", ok),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "invalid company id in token")
|
||||
}
|
||||
|
||||
if slugID.Value != tokenCID.Value {
|
||||
a.mongoLoggerSvc.Error("token company-id doesn't match the slug company_id",
|
||||
zap.Time("timestamp", time.Now()),
|
||||
)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "invalid company_id")
|
||||
}
|
||||
|
||||
fmt.Printf("\nTenant successfully authenticated!\n")
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,17 +62,42 @@ func (a *App) initAppRoutes() {
|
|||
})
|
||||
})
|
||||
|
||||
a.fiber.Get("/routes", func(c *fiber.Ctx) error {
|
||||
return c.JSON(a.fiber.Stack()) // prints all registered routes
|
||||
})
|
||||
|
||||
// Groups
|
||||
groupV1 := a.fiber.Group("/api/v1")
|
||||
tenant := groupV1.Group("/:tenant_slug", a.TenantMiddleware)
|
||||
tenantAuth := groupV1.Group("/:tenant_slug", a.authMiddleware, a.TenantMiddleware)
|
||||
tenant := groupV1.Group("/tenant/:tenant_slug", a.TenantMiddleware)
|
||||
tenant.Get("/test", a.authMiddleware, a.authMiddleware, func(c *fiber.Ctx) error {
|
||||
fmt.Printf("\nTest Route %v\n", c.Route().Path)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
|
||||
fmt.Printf("In the tenant auth test \n")
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Is is fine",
|
||||
})
|
||||
})
|
||||
tenant.Get("/", func(c *fiber.Ctx) error {
|
||||
fmt.Printf("\nTenant Route %v\n", c.Route().Path)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
if !companyID.Valid {
|
||||
h.BadRequestLogger().Error("invalid company id")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Company Tenant Active",
|
||||
})
|
||||
})
|
||||
//Direct_deposit
|
||||
groupV1.Post("/direct_deposit", a.authMiddleware, h.InitiateDirectDeposit)
|
||||
groupV1.Post("/direct_deposit/verify", a.authMiddleware, h.VerifyDirectDeposit)
|
||||
groupV1.Get("/direct_deposit/pending", a.authMiddleware, h.GetPendingDirectDeposits)
|
||||
|
||||
|
||||
// Swagger
|
||||
a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())
|
||||
|
||||
|
|
@ -141,28 +166,29 @@ func (a *App) initAppRoutes() {
|
|||
// groupV1.Post("/arifpay/transaction-id/verify-transaction", a.authMiddleware, h.ArifpayVerifyByTransactionIDHandler)
|
||||
// groupV1.Get("/arifpay/session-id/verify-transaction/:session_id", a.authMiddleware, h.ArifpayVerifyBySessionIDHandler)
|
||||
|
||||
|
||||
|
||||
|
||||
// User Routes
|
||||
tenant.Post("/user/resetPassword", h.ResetPassword)
|
||||
tenant.Post("/user/sendResetCode", h.SendResetCode)
|
||||
groupV1.Post("/user/resetPassword", h.ResetPassword)
|
||||
groupV1.Post("/user/sendResetCode", h.SendResetCode)
|
||||
|
||||
tenant.Post("/user/resetPassword", h.ResetTenantPassword)
|
||||
tenant.Post("/user/sendResetCode", h.SendTenantResetCode)
|
||||
tenant.Post("/user/register", h.RegisterUser)
|
||||
tenant.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
||||
tenant.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
||||
tenantAuth.Get("/user/customer-profile", h.CustomerProfile)
|
||||
tenantAuth.Get("/user/admin-profile", h.AdminProfile)
|
||||
tenantAuth.Get("/user/bets", h.GetBetByUserID)
|
||||
|
||||
tenant.Get("/user/customer-profile", a.authMiddleware, h.CustomerProfile)
|
||||
tenant.Get("/user/admin-profile", a.authMiddleware, h.AdminProfile)
|
||||
tenant.Get("/user/bets", a.authMiddleware, h.GetBetByUserID)
|
||||
|
||||
groupV1.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
||||
groupV1.Post("/user/suspend", a.authMiddleware, h.UpdateUserSuspend)
|
||||
groupV1.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
|
||||
tenantAuth.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||
tenantAuth.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||
tenant.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||
tenant.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||
|
||||
// Referral Routes
|
||||
groupV1.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
||||
groupV1.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
||||
tenant.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
|
||||
tenant.Get("/referral/stats", a.authMiddleware, h.GetReferralStats)
|
||||
groupV1.Post("/referral/settings", a.authMiddleware, h.CreateReferralSettings)
|
||||
groupV1.Get("/referral/settings", a.authMiddleware, h.GetReferralSettings)
|
||||
groupV1.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
|
||||
|
|
@ -177,15 +203,26 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
||||
groupV1.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
||||
|
||||
tenant.Get("/customer", a.authMiddleware, h.GetAllTenantCustomers)
|
||||
tenant.Get("/customer/:id", a.authMiddleware, h.GetTenantCustomerByID)
|
||||
tenant.Put("/customer/:id", a.authMiddleware, h.UpdateTenantCustomer)
|
||||
tenant.Get("/customer/:id/bets", a.authMiddleware, h.GetTenantCustomerBets)
|
||||
|
||||
groupV1.Get("/customer", a.authMiddleware, a.SuperAdminOnly, h.GetAllCustomers)
|
||||
groupV1.Get("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCustomerByID)
|
||||
groupV1.Put("/customer/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCustomer)
|
||||
tenant.Get("/customer/:id/bets", a.authMiddleware, h.GetCustomerBets)
|
||||
|
||||
groupV1.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
||||
groupV1.Get("/admin/:id", a.authMiddleware, h.GetAdminByID)
|
||||
groupV1.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
||||
groupV1.Put("/admin/:id", a.authMiddleware, h.UpdateAdmin)
|
||||
|
||||
groupV1.Get("/t-approver", a.authMiddleware, h.GetAllTransactionApprovers)
|
||||
groupV1.Get("/t-approver/:id", a.authMiddleware, h.GetTransactionApproverByID)
|
||||
groupV1.Post("/t-approver", a.authMiddleware, h.CreateTransactionApprover)
|
||||
groupV1.Put("/t-approver/:id", a.authMiddleware, h.UpdateTransactionApprover)
|
||||
|
||||
groupV1.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
||||
groupV1.Get("/managers/:id", a.authMiddleware, h.GetManagerByID)
|
||||
groupV1.Post("/managers", a.authMiddleware, h.CreateManager)
|
||||
|
|
@ -200,8 +237,8 @@ func (a *App) initAppRoutes() {
|
|||
tenant.Get("/odds/upcoming/:upcoming_id", h.GetTenantOddsByUpcomingID)
|
||||
tenant.Get("/odds/upcoming/:upcoming_id/market/:market_id", h.GetTenantOddsByMarketID)
|
||||
|
||||
groupV1.Get("/events", a.authMiddleware, a.SuperAdminOnly, h.GetAllUpcomingEvents)
|
||||
groupV1.Get("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.GetUpcomingEventByID)
|
||||
groupV1.Get("/events", a.authMiddleware, h.GetAllUpcomingEvents)
|
||||
groupV1.Get("/events/:id", a.authMiddleware, h.GetUpcomingEventByID)
|
||||
groupV1.Delete("/events/:id", a.authMiddleware, a.SuperAdminOnly, h.SetEventStatusToRemoved)
|
||||
|
||||
tenant.Get("/events", h.GetTenantUpcomingEvents)
|
||||
|
|
@ -221,6 +258,7 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Post("/branch", a.authMiddleware, h.CreateBranch)
|
||||
groupV1.Get("/branch", a.authMiddleware, h.GetAllBranches)
|
||||
groupV1.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
|
||||
groupV1.Post("/branch/:id/return", a.authMiddleware, h.ReturnBranchWallet)
|
||||
groupV1.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
|
||||
groupV1.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
|
||||
groupV1.Put("/branch/:id/set-active", a.authMiddleware, h.UpdateBranchStatus)
|
||||
|
|
@ -258,15 +296,19 @@ func (a *App) initAppRoutes() {
|
|||
tenant.Get("/ticket/:id", h.GetTicketByID)
|
||||
|
||||
// Bet Routes
|
||||
tenantAuth.Post("/sport/bet", h.CreateBet)
|
||||
tenantAuth.Post("/sport/bet/fastcode", h.CreateBetWithFastCode)
|
||||
tenant.Post("/sport/bet", a.authMiddleware, h.CreateBet)
|
||||
tenant.Post("/sport/bet/fastcode", a.authMiddleware, h.CreateBetWithFastCode)
|
||||
tenant.Get("/sport/bet/fastcode/:fast_code", h.GetBetByFastCode)
|
||||
tenantAuth.Get("/sport/bet", h.GetAllBet)
|
||||
tenantAuth.Get("/sport/bet/:id", h.GetBetByID)
|
||||
tenantAuth.Patch("/sport/bet/:id", h.UpdateCashOut)
|
||||
tenantAuth.Delete("/sport/bet/:id", h.DeleteBet)
|
||||
tenant.Get("/sport/bet", a.authMiddleware, h.GetAllTenantBets)
|
||||
tenant.Get("/sport/bet/:id", a.authMiddleware, h.GetTenantBetByID)
|
||||
tenant.Patch("/sport/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
||||
tenant.Delete("/sport/bet/:id", a.authMiddleware, h.DeleteTenantBet)
|
||||
|
||||
tenantAuth.Post("/sport/random/bet", h.RandomBet)
|
||||
groupV1.Get("/sport/bet", a.authMiddleware, a.SuperAdminOnly, h.GetAllBet)
|
||||
groupV1.Get("/sport/bet/:id", a.authMiddleware, a.SuperAdminOnly, h.GetBetByID)
|
||||
groupV1.Delete("/sport/bet/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteBet)
|
||||
|
||||
tenant.Post("/sport/random/bet", a.authMiddleware, h.RandomBet)
|
||||
|
||||
// Wallet
|
||||
groupV1.Get("/wallet", h.GetAllWallets)
|
||||
|
|
@ -373,9 +415,9 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Get("/settings/:key", a.authMiddleware, a.SuperAdminOnly, h.GetGlobalSettingByKey)
|
||||
groupV1.Put("/settings", a.authMiddleware, a.SuperAdminOnly, h.UpdateGlobalSettingList)
|
||||
|
||||
tenantAuth.Post("/settings", h.SaveCompanySettingList)
|
||||
tenantAuth.Get("/settings", h.GetCompanySettingList)
|
||||
tenantAuth.Delete("/settings/:key", h.DeleteCompanySetting)
|
||||
tenantAuth.Delete("/settings", h.DeleteAllCompanySetting)
|
||||
tenant.Post("/settings", a.authMiddleware, h.SaveCompanySettingList)
|
||||
tenant.Get("/settings", a.authMiddleware, h.GetCompanySettingList)
|
||||
tenant.Delete("/settings/:key", a.authMiddleware, h.DeleteCompanySetting)
|
||||
tenant.Delete("/settings", a.authMiddleware, h.DeleteAllCompanySetting)
|
||||
|
||||
}
|
||||
|
|
|
|||
18
makefile
18
makefile
|
|
@ -56,8 +56,19 @@ restore:
|
|||
restore_file:
|
||||
@echo "Restoring latest backup..."
|
||||
gunzip -c $(file) | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||
|
||||
.PHONY: seed_data
|
||||
seed_data:
|
||||
cat db/data/seed_data.sql | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh
|
||||
|
||||
@echo "Waiting for PostgreSQL to be ready..."
|
||||
@until docker exec fortunebet-backend-postgres-1 pg_isready -U root -d gh; do \
|
||||
echo "PostgreSQL is not ready yet..."; \
|
||||
sleep 1; \
|
||||
done
|
||||
@for file in db/data/*.sql; do \
|
||||
echo "Seeding $$file..."; \
|
||||
cat $$file | docker exec -i fortunebet-backend-postgres-1 psql -U root -d gh; \
|
||||
done
|
||||
postgres_log:
|
||||
docker logs fortunebet-backend-postgres-1
|
||||
.PHONY: swagger
|
||||
|
|
@ -69,11 +80,12 @@ logs:
|
|||
@mkdir -p logs
|
||||
db-up: | logs
|
||||
@mkdir -p logs
|
||||
@docker compose up -d postgres migrate mongo redis
|
||||
@docker compose up -d postgres migrate mongo redis --wait migrate
|
||||
@make seed_data
|
||||
@docker logs fortunebet-backend-postgres-1 > logs/postgres.log 2>&1 &
|
||||
.PHONY: db-down
|
||||
db-down:
|
||||
@docker compose down
|
||||
@docker compose down -v
|
||||
@docker volume rm fortunebet-backend_postgres_data
|
||||
.PHONY: sqlc-gen
|
||||
sqlc-gen:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user