integration fixes
This commit is contained in:
parent
fcd926223a
commit
208a2d74be
|
|
@ -10,8 +10,9 @@ CREATE TABLE IF NOT EXISTS users (
|
|||
phone_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ,
|
||||
--
|
||||
suspended_at TIMESTAMPTZ NULL, -- this can be NULL if the user is not suspended
|
||||
company_id BIGINT,
|
||||
suspended_at TIMESTAMPTZ NULL,
|
||||
-- this can be NULL if the user is not suspended
|
||||
suspended BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
CHECK (
|
||||
email IS NOT NULL
|
||||
|
|
@ -53,6 +54,7 @@ CREATE TABLE IF NOT EXISTS bets (
|
|||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
is_shop_bet BOOLEAN NOT NULL,
|
||||
UNIQUE(cashout_id),
|
||||
CHECK (
|
||||
user_id IS NOT NULL
|
||||
OR branch_id IS NOT NULL
|
||||
|
|
@ -148,6 +150,7 @@ CREATE TABLE IF NOT EXISTS transactions (
|
|||
branch_id BIGINT NOT NULL,
|
||||
cashier_id BIGINT NOT NULL,
|
||||
bet_id BIGINT NOT NULL,
|
||||
number_of_outcomes BIGINT NOT NULL,
|
||||
type BIGINT NOT NULL,
|
||||
payment_option BIGINT NOT NULL,
|
||||
full_name VARCHAR(255) NOT NULL,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
CREATE TYPE ReferralStatus AS ENUM ('PENDING', 'COMPLETED', 'EXPIRED', 'CANCELLED');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS referral_settings (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
referral_reward_amount DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
|
|
@ -17,7 +16,6 @@ CREATE TABLE IF NOT EXISTS referral_settings (
|
|||
AND cashback_percentage <= 100
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS referrals (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
referral_code VARCHAR(10) NOT NULL UNIQUE,
|
||||
|
|
@ -29,25 +27,20 @@ CREATE TABLE IF NOT EXISTS referrals (
|
|||
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),
|
||||
FOREIGN KEY (referred_id) REFERENCES users (id),
|
||||
-- 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)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_referrals_referral_code ON referrals (referral_code);
|
||||
|
||||
CREATE INDEX idx_referrals_referrer_id ON referrals (referrer_id);
|
||||
|
||||
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);
|
||||
|
||||
ADD COLUMN IF NOT EXISTS referred_by VARCHAR(10);
|
||||
-- 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,
|
||||
ADD CONSTRAINT bonus_balance_positive CHECK (bonus_balance >= 0),
|
||||
ADD CONSTRAINT cash_balance_positive CHECK (cash_balance >= 0);
|
||||
ADD COLUMN IF NOT EXISTS cash_balance DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
ADD CONSTRAINT bonus_balance_positive CHECK (bonus_balance >= 0),
|
||||
ADD CONSTRAINT cash_balance_positive CHECK (cash_balance >= 0);
|
||||
|
|
@ -1,16 +1,20 @@
|
|||
-- name: GetUserByEmailPhone :one
|
||||
SELECT * FROM users
|
||||
WHERE email = $1 OR phone_number = $2;
|
||||
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
OR phone_number = $2;
|
||||
-- name: CreateRefreshToken :exec
|
||||
INSERT INTO refresh_tokens (user_id, token, expires_at, created_at, revoked)
|
||||
VALUES ($1, $2, $3, $4, $5);
|
||||
|
||||
-- name: GetRefreshToken :one
|
||||
SELECT * FROM refresh_tokens
|
||||
SELECT *
|
||||
FROM refresh_tokens
|
||||
WHERE token = $1;
|
||||
|
||||
-- name: GetRefreshTokenByUserID :one
|
||||
SELECT *
|
||||
FROM refresh_tokens
|
||||
WHERE user_id = $1;
|
||||
-- name: RevokeRefreshToken :exec
|
||||
UPDATE refresh_tokens
|
||||
SET revoked = TRUE
|
||||
UPDATE refresh_tokens
|
||||
SET revoked = TRUE
|
||||
WHERE token = $1;
|
||||
|
|
@ -13,6 +13,10 @@ FROM companies;
|
|||
SELECT *
|
||||
FROM companies
|
||||
WHERE id = $1;
|
||||
-- name: SearchCompanyByName :many
|
||||
SELECT *
|
||||
FROM companies
|
||||
WHERE name ILIKE '%' || $1 || '%';
|
||||
-- name: UpdateCompany :one
|
||||
UPDATE companies
|
||||
SET name = $1,
|
||||
|
|
|
|||
|
|
@ -9,9 +9,24 @@ INSERT INTO users (
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
RETURNING id,
|
||||
first_name,
|
||||
last_name,
|
||||
|
|
@ -21,7 +36,9 @@ RETURNING id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at;
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id;
|
||||
-- name: GetUserByID :one
|
||||
SELECT *
|
||||
FROM users
|
||||
|
|
@ -36,8 +53,31 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM users;
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
wHERE (
|
||||
role = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
LIMIT $3 OFFSET $4;
|
||||
-- name: GetTotalUsers :one
|
||||
SELECT COUNT(*)
|
||||
FROM users
|
||||
wHERE (
|
||||
role = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
);
|
||||
-- name: SearchUserByNameOrPhone :many
|
||||
SELECT id,
|
||||
first_name,
|
||||
|
|
@ -48,7 +88,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE first_name ILIKE '%' || $1 || '%'
|
||||
OR last_name ILIKE '%' || $1 || '%'
|
||||
|
|
@ -62,6 +105,12 @@ SET first_name = $1,
|
|||
role = $5,
|
||||
updated_at = $6
|
||||
WHERE id = $7;
|
||||
-- name: SuspendUser :exec
|
||||
UPDATE users
|
||||
SET suspended = $1,
|
||||
suspended_at = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $3;
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM users
|
||||
WHERE id = $1;
|
||||
|
|
@ -88,7 +137,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE email = $1;
|
||||
-- name: GetUserByPhone :one
|
||||
|
|
@ -101,7 +153,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE phone_number = $1;
|
||||
-- name: UpdatePassword :exec
|
||||
|
|
|
|||
673
docs/docs.go
673
docs/docs.go
|
|
@ -24,6 +24,111 @@ const docTemplate = `{
|
|||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {
|
||||
"/admin": {
|
||||
"get": {
|
||||
"description": "Get all Admins",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"admin"
|
||||
],
|
||||
"summary": "Get all Admins",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "page_size",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create Admin",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"admin"
|
||||
],
|
||||
"summary": "Create Admin",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create admin",
|
||||
"name": "manger",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.CreateAdminReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/login": {
|
||||
"post": {
|
||||
"description": "Login customer",
|
||||
|
|
@ -955,6 +1060,13 @@ const docTemplate = `{
|
|||
],
|
||||
"summary": "Update cashier",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Cashier ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update cashier",
|
||||
"name": "cashier",
|
||||
|
|
@ -1361,7 +1473,7 @@ const docTemplate = `{
|
|||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create Managers",
|
||||
"description": "Create Manager",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
|
@ -1371,7 +1483,7 @@ const docTemplate = `{
|
|||
"tags": [
|
||||
"manager"
|
||||
],
|
||||
"summary": "Create Managers",
|
||||
"summary": "Create Manager",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create manager",
|
||||
|
|
@ -1803,6 +1915,147 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/referral/settings": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Retrieves current referral settings (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Get referral settings",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralSettings"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Updates referral settings (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Update referral settings",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Referral settings",
|
||||
"name": "settings",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralSettings"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/referral/stats": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Retrieves referral statistics for the authenticated user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Get referral statistics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralStats"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/search/branch": {
|
||||
"get": {
|
||||
"description": "Search branches by name or location",
|
||||
|
|
@ -1850,6 +2103,44 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/search/company": {
|
||||
"get": {
|
||||
"description": "Gets all companies",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"company"
|
||||
],
|
||||
"summary": "Gets all companies",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/handlers.CompanyRes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/supportedOperation": {
|
||||
"get": {
|
||||
"description": "Gets all supported operations",
|
||||
|
|
@ -2184,7 +2475,7 @@ const docTemplate = `{
|
|||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Updates the cashed out field",
|
||||
"description": "Updates the verified status of a transaction",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
|
@ -2194,7 +2485,7 @@ const docTemplate = `{
|
|||
"tags": [
|
||||
"transaction"
|
||||
],
|
||||
"summary": "Updates the cashed out field",
|
||||
"summary": "Updates the verified field of a transaction",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
|
|
@ -2205,7 +2496,7 @@ const docTemplate = `{
|
|||
},
|
||||
{
|
||||
"description": "Updates Transaction Verification",
|
||||
"name": "updateCashOut",
|
||||
"name": "updateVerified",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
|
|
@ -2689,6 +2980,56 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/user/single/{id}": {
|
||||
"get": {
|
||||
"description": "Get a single user by id",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Get user by id",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/wallet": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2738,6 +3079,109 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/virtual-game/callback": {
|
||||
"post": {
|
||||
"description": "Processes callbacks from PopOK for game events",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"virtual-game"
|
||||
],
|
||||
"summary": "Handle PopOK game callback",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Callback data",
|
||||
"name": "callback",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.PopOKCallback"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/virtual-game/launch": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Generates a URL to launch a PopOK game",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"virtual-game"
|
||||
],
|
||||
"summary": "Launch a PopOK virtual game",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Game launch details",
|
||||
"name": "launch",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.launchVirtualGameReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.launchVirtualGameRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/wallet": {
|
||||
"get": {
|
||||
"description": "Retrieve all wallets",
|
||||
|
|
@ -3019,6 +3463,34 @@ const docTemplate = `{
|
|||
"BANK"
|
||||
]
|
||||
},
|
||||
"domain.PopOKCallback": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "number"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"signature": {
|
||||
"description": "HMAC-SHA256 signature for verification",
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "integer"
|
||||
},
|
||||
"transaction_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"description": "BET, WIN, REFUND, JACKPOT_WIN",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.RawOddsByMarketID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -3040,6 +3512,58 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"betReferralBonusPercentage": {
|
||||
"type": "number"
|
||||
},
|
||||
"cashbackPercentage": {
|
||||
"type": "number"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"expiresAfterDays": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"maxReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"referralRewardAmount": {
|
||||
"type": "number"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"completedReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pendingRewards": {
|
||||
"type": "number"
|
||||
},
|
||||
"totalReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"totalRewardEarned": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.Role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
@ -3327,6 +3851,9 @@ const docTemplate = `{
|
|||
},
|
||||
"handlers.CheckPhoneEmailExistReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone_number"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -3370,11 +3897,39 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.CreateAdminReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"company_id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string",
|
||||
"example": "John"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string",
|
||||
"example": "Doe"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"example": "password123"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.CreateBetOutcomeReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"event_id": {
|
||||
"description": "BetID int64 ` + "`" + `json:\"bet_id\" example:\"1\"` + "`" + `",
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
|
|
@ -3399,10 +3954,6 @@ const docTemplate = `{
|
|||
"type": "string",
|
||||
"example": "John"
|
||||
},
|
||||
"is_shop_bet": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"outcomes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
@ -3497,6 +4048,10 @@ const docTemplate = `{
|
|||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3516,6 +4071,10 @@ const docTemplate = `{
|
|||
"handlers.CreateManagerReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"company_id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
|
|
@ -3737,7 +4296,6 @@ const docTemplate = `{
|
|||
"example": "Doe"
|
||||
},
|
||||
"otp": {
|
||||
"description": "Role string",
|
||||
"type": "string",
|
||||
"example": "123456"
|
||||
},
|
||||
|
|
@ -3770,18 +4328,27 @@ const docTemplate = `{
|
|||
},
|
||||
"handlers.ResetPasswordReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"otp",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"otp": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "123456"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"example": "newpassword123"
|
||||
},
|
||||
"phoneNumber": {
|
||||
"type": "string"
|
||||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3872,6 +4439,10 @@ const docTemplate = `{
|
|||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"number_of_outcomes": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"payment_option": {
|
||||
"allOf": [
|
||||
{
|
||||
|
|
@ -3952,17 +4523,25 @@ const docTemplate = `{
|
|||
},
|
||||
"handlers.UpdateTransactionVerifiedReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"verified"
|
||||
],
|
||||
"properties": {
|
||||
"verified": {
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.UpdateWalletActiveReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"is_active"
|
||||
],
|
||||
"properties": {
|
||||
"isActive": {
|
||||
"type": "boolean"
|
||||
"is_active": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3984,6 +4563,9 @@ const docTemplate = `{
|
|||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4046,8 +4628,45 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.launchVirtualGameReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"currency",
|
||||
"game_id",
|
||||
"mode"
|
||||
],
|
||||
"properties": {
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"example": "USD"
|
||||
},
|
||||
"game_id": {
|
||||
"type": "string",
|
||||
"example": "crash_001"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"REAL",
|
||||
"DEMO"
|
||||
],
|
||||
"example": "REAL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.launchVirtualGameRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"launch_url": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.loginCustomerReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -4079,20 +4698,30 @@ const docTemplate = `{
|
|||
},
|
||||
"handlers.logoutReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"refresh_token"
|
||||
],
|
||||
"properties": {
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003crefresh-token\u003e"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.refreshToken": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"access_token",
|
||||
"refresh_token"
|
||||
],
|
||||
"properties": {
|
||||
"access_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003cjwt-token\u003e"
|
||||
},
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003crefresh-token\u003e"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,6 +16,111 @@
|
|||
"version": "1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/admin": {
|
||||
"get": {
|
||||
"description": "Get all Admins",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"admin"
|
||||
],
|
||||
"summary": "Get all Admins",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "page_size",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create Admin",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"admin"
|
||||
],
|
||||
"summary": "Create Admin",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create admin",
|
||||
"name": "manger",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.CreateAdminReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/login": {
|
||||
"post": {
|
||||
"description": "Login customer",
|
||||
|
|
@ -947,6 +1052,13 @@
|
|||
],
|
||||
"summary": "Update cashier",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Cashier ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update cashier",
|
||||
"name": "cashier",
|
||||
|
|
@ -1353,7 +1465,7 @@
|
|||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create Managers",
|
||||
"description": "Create Manager",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
|
@ -1363,7 +1475,7 @@
|
|||
"tags": [
|
||||
"manager"
|
||||
],
|
||||
"summary": "Create Managers",
|
||||
"summary": "Create Manager",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create manager",
|
||||
|
|
@ -1795,6 +1907,147 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/referral/settings": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Retrieves current referral settings (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Get referral settings",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralSettings"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Updates referral settings (admin only)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Update referral settings",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Referral settings",
|
||||
"name": "settings",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralSettings"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/referral/stats": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Retrieves referral statistics for the authenticated user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"referral"
|
||||
],
|
||||
"summary": "Get referral statistics",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ReferralStats"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/search/branch": {
|
||||
"get": {
|
||||
"description": "Search branches by name or location",
|
||||
|
|
@ -1842,6 +2095,44 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/search/company": {
|
||||
"get": {
|
||||
"description": "Gets all companies",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"company"
|
||||
],
|
||||
"summary": "Gets all companies",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/handlers.CompanyRes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/supportedOperation": {
|
||||
"get": {
|
||||
"description": "Gets all supported operations",
|
||||
|
|
@ -2176,7 +2467,7 @@
|
|||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Updates the cashed out field",
|
||||
"description": "Updates the verified status of a transaction",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
|
@ -2186,7 +2477,7 @@
|
|||
"tags": [
|
||||
"transaction"
|
||||
],
|
||||
"summary": "Updates the cashed out field",
|
||||
"summary": "Updates the verified field of a transaction",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
|
|
@ -2197,7 +2488,7 @@
|
|||
},
|
||||
{
|
||||
"description": "Updates Transaction Verification",
|
||||
"name": "updateCashOut",
|
||||
"name": "updateVerified",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
|
|
@ -2681,6 +2972,56 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/user/single/{id}": {
|
||||
"get": {
|
||||
"description": "Get a single user by id",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Get user by id",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/wallet": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2730,6 +3071,109 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/virtual-game/callback": {
|
||||
"post": {
|
||||
"description": "Processes callbacks from PopOK for game events",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"virtual-game"
|
||||
],
|
||||
"summary": "Handle PopOK game callback",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Callback data",
|
||||
"name": "callback",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.PopOKCallback"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/virtual-game/launch": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Generates a URL to launch a PopOK game",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"virtual-game"
|
||||
],
|
||||
"summary": "Launch a PopOK virtual game",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Game launch details",
|
||||
"name": "launch",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.launchVirtualGameReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.launchVirtualGameRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/wallet": {
|
||||
"get": {
|
||||
"description": "Retrieve all wallets",
|
||||
|
|
@ -3011,6 +3455,34 @@
|
|||
"BANK"
|
||||
]
|
||||
},
|
||||
"domain.PopOKCallback": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "number"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"signature": {
|
||||
"description": "HMAC-SHA256 signature for verification",
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "integer"
|
||||
},
|
||||
"transaction_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"description": "BET, WIN, REFUND, JACKPOT_WIN",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.RawOddsByMarketID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -3032,6 +3504,58 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"betReferralBonusPercentage": {
|
||||
"type": "number"
|
||||
},
|
||||
"cashbackPercentage": {
|
||||
"type": "number"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"expiresAfterDays": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"maxReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"referralRewardAmount": {
|
||||
"type": "number"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"completedReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pendingRewards": {
|
||||
"type": "number"
|
||||
},
|
||||
"totalReferrals": {
|
||||
"type": "integer"
|
||||
},
|
||||
"totalRewardEarned": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.Role": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
@ -3319,6 +3843,9 @@
|
|||
},
|
||||
"handlers.CheckPhoneEmailExistReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone_number"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -3362,11 +3889,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.CreateAdminReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"company_id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string",
|
||||
"example": "John"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string",
|
||||
"example": "Doe"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"example": "password123"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.CreateBetOutcomeReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"event_id": {
|
||||
"description": "BetID int64 `json:\"bet_id\" example:\"1\"`",
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
|
|
@ -3391,10 +3946,6 @@
|
|||
"type": "string",
|
||||
"example": "John"
|
||||
},
|
||||
"is_shop_bet": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"outcomes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
@ -3489,6 +4040,10 @@
|
|||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3508,6 +4063,10 @@
|
|||
"handlers.CreateManagerReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"company_id": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
|
|
@ -3729,7 +4288,6 @@
|
|||
"example": "Doe"
|
||||
},
|
||||
"otp": {
|
||||
"description": "Role string",
|
||||
"type": "string",
|
||||
"example": "123456"
|
||||
},
|
||||
|
|
@ -3762,18 +4320,27 @@
|
|||
},
|
||||
"handlers.ResetPasswordReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"otp",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"otp": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "123456"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"example": "newpassword123"
|
||||
},
|
||||
"phoneNumber": {
|
||||
"type": "string"
|
||||
"phone_number": {
|
||||
"type": "string",
|
||||
"example": "1234567890"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3864,6 +4431,10 @@
|
|||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"number_of_outcomes": {
|
||||
"type": "integer",
|
||||
"example": 1
|
||||
},
|
||||
"payment_option": {
|
||||
"allOf": [
|
||||
{
|
||||
|
|
@ -3944,17 +4515,25 @@
|
|||
},
|
||||
"handlers.UpdateTransactionVerifiedReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"verified"
|
||||
],
|
||||
"properties": {
|
||||
"verified": {
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.UpdateWalletActiveReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"is_active"
|
||||
],
|
||||
"properties": {
|
||||
"isActive": {
|
||||
"type": "boolean"
|
||||
"is_active": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -3976,6 +4555,9 @@
|
|||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4038,8 +4620,45 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.launchVirtualGameReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"currency",
|
||||
"game_id",
|
||||
"mode"
|
||||
],
|
||||
"properties": {
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"example": "USD"
|
||||
},
|
||||
"game_id": {
|
||||
"type": "string",
|
||||
"example": "crash_001"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"REAL",
|
||||
"DEMO"
|
||||
],
|
||||
"example": "REAL"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.launchVirtualGameRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"launch_url": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.loginCustomerReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -4071,20 +4690,30 @@
|
|||
},
|
||||
"handlers.logoutReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"refresh_token"
|
||||
],
|
||||
"properties": {
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003crefresh-token\u003e"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.refreshToken": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"access_token",
|
||||
"refresh_token"
|
||||
],
|
||||
"properties": {
|
||||
"access_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003cjwt-token\u003e"
|
||||
},
|
||||
"refresh_token": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "\u003crefresh-token\u003e"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -103,6 +103,25 @@ definitions:
|
|||
- TELEBIRR_TRANSACTION
|
||||
- ARIFPAY_TRANSACTION
|
||||
- BANK
|
||||
domain.PopOKCallback:
|
||||
properties:
|
||||
amount:
|
||||
type: number
|
||||
currency:
|
||||
type: string
|
||||
session_id:
|
||||
type: string
|
||||
signature:
|
||||
description: HMAC-SHA256 signature for verification
|
||||
type: string
|
||||
timestamp:
|
||||
type: integer
|
||||
transaction_id:
|
||||
type: string
|
||||
type:
|
||||
description: BET, WIN, REFUND, JACKPOT_WIN
|
||||
type: string
|
||||
type: object
|
||||
domain.RawOddsByMarketID:
|
||||
properties:
|
||||
fetched_at:
|
||||
|
|
@ -117,6 +136,40 @@ definitions:
|
|||
items: {}
|
||||
type: array
|
||||
type: object
|
||||
domain.ReferralSettings:
|
||||
properties:
|
||||
betReferralBonusPercentage:
|
||||
type: number
|
||||
cashbackPercentage:
|
||||
type: number
|
||||
createdAt:
|
||||
type: string
|
||||
expiresAfterDays:
|
||||
type: integer
|
||||
id:
|
||||
type: integer
|
||||
maxReferrals:
|
||||
type: integer
|
||||
referralRewardAmount:
|
||||
type: number
|
||||
updatedAt:
|
||||
type: string
|
||||
updatedBy:
|
||||
type: string
|
||||
version:
|
||||
type: integer
|
||||
type: object
|
||||
domain.ReferralStats:
|
||||
properties:
|
||||
completedReferrals:
|
||||
type: integer
|
||||
pendingRewards:
|
||||
type: number
|
||||
totalReferrals:
|
||||
type: integer
|
||||
totalRewardEarned:
|
||||
type: number
|
||||
type: object
|
||||
domain.Role:
|
||||
enum:
|
||||
- super_admin
|
||||
|
|
@ -331,6 +384,8 @@ definitions:
|
|||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
required:
|
||||
- phone_number
|
||||
type: object
|
||||
handlers.CheckPhoneEmailExistRes:
|
||||
properties:
|
||||
|
|
@ -354,10 +409,30 @@ definitions:
|
|||
example: 1
|
||||
type: integer
|
||||
type: object
|
||||
handlers.CreateAdminReq:
|
||||
properties:
|
||||
company_id:
|
||||
example: 1
|
||||
type: integer
|
||||
email:
|
||||
example: john.doe@example.com
|
||||
type: string
|
||||
first_name:
|
||||
example: John
|
||||
type: string
|
||||
last_name:
|
||||
example: Doe
|
||||
type: string
|
||||
password:
|
||||
example: password123
|
||||
type: string
|
||||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
type: object
|
||||
handlers.CreateBetOutcomeReq:
|
||||
properties:
|
||||
event_id:
|
||||
description: BetID int64 `json:"bet_id" example:"1"`
|
||||
example: 1
|
||||
type: integer
|
||||
market_id:
|
||||
|
|
@ -375,9 +450,6 @@ definitions:
|
|||
full_name:
|
||||
example: John
|
||||
type: string
|
||||
is_shop_bet:
|
||||
example: false
|
||||
type: boolean
|
||||
outcomes:
|
||||
items:
|
||||
$ref: '#/definitions/handlers.CreateBetOutcomeReq'
|
||||
|
|
@ -444,6 +516,9 @@ definitions:
|
|||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
suspended:
|
||||
example: false
|
||||
type: boolean
|
||||
type: object
|
||||
handlers.CreateCompanyReq:
|
||||
properties:
|
||||
|
|
@ -456,6 +531,9 @@ definitions:
|
|||
type: object
|
||||
handlers.CreateManagerReq:
|
||||
properties:
|
||||
company_id:
|
||||
example: 1
|
||||
type: integer
|
||||
email:
|
||||
example: john.doe@example.com
|
||||
type: string
|
||||
|
|
@ -611,7 +689,6 @@ definitions:
|
|||
example: Doe
|
||||
type: string
|
||||
otp:
|
||||
description: Role string
|
||||
example: "123456"
|
||||
type: string
|
||||
password:
|
||||
|
|
@ -636,13 +713,21 @@ definitions:
|
|||
handlers.ResetPasswordReq:
|
||||
properties:
|
||||
email:
|
||||
example: john.doe@example.com
|
||||
type: string
|
||||
otp:
|
||||
example: "123456"
|
||||
type: string
|
||||
password:
|
||||
example: newpassword123
|
||||
minLength: 8
|
||||
type: string
|
||||
phoneNumber:
|
||||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
required:
|
||||
- otp
|
||||
- password
|
||||
type: object
|
||||
handlers.SearchUserByNameOrPhoneReq:
|
||||
properties:
|
||||
|
|
@ -705,6 +790,9 @@ definitions:
|
|||
id:
|
||||
example: 1
|
||||
type: integer
|
||||
number_of_outcomes:
|
||||
example: 1
|
||||
type: integer
|
||||
payment_option:
|
||||
allOf:
|
||||
- $ref: '#/definitions/domain.PaymentOption'
|
||||
|
|
@ -762,12 +850,18 @@ definitions:
|
|||
handlers.UpdateTransactionVerifiedReq:
|
||||
properties:
|
||||
verified:
|
||||
example: true
|
||||
type: boolean
|
||||
required:
|
||||
- verified
|
||||
type: object
|
||||
handlers.UpdateWalletActiveReq:
|
||||
properties:
|
||||
isActive:
|
||||
is_active:
|
||||
example: true
|
||||
type: boolean
|
||||
required:
|
||||
- is_active
|
||||
type: object
|
||||
handlers.UserProfileRes:
|
||||
properties:
|
||||
|
|
@ -781,6 +875,8 @@ definitions:
|
|||
type: string
|
||||
id:
|
||||
type: integer
|
||||
last_login:
|
||||
type: string
|
||||
last_name:
|
||||
type: string
|
||||
phone_number:
|
||||
|
|
@ -824,6 +920,30 @@ definitions:
|
|||
example: 1
|
||||
type: integer
|
||||
type: object
|
||||
handlers.launchVirtualGameReq:
|
||||
properties:
|
||||
currency:
|
||||
example: USD
|
||||
type: string
|
||||
game_id:
|
||||
example: crash_001
|
||||
type: string
|
||||
mode:
|
||||
enum:
|
||||
- REAL
|
||||
- DEMO
|
||||
example: REAL
|
||||
type: string
|
||||
required:
|
||||
- currency
|
||||
- game_id
|
||||
- mode
|
||||
type: object
|
||||
handlers.launchVirtualGameRes:
|
||||
properties:
|
||||
launch_url:
|
||||
type: string
|
||||
type: object
|
||||
handlers.loginCustomerReq:
|
||||
properties:
|
||||
email:
|
||||
|
|
@ -835,6 +955,8 @@ definitions:
|
|||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
required:
|
||||
- password
|
||||
type: object
|
||||
handlers.loginCustomerRes:
|
||||
properties:
|
||||
|
|
@ -848,14 +970,22 @@ definitions:
|
|||
handlers.logoutReq:
|
||||
properties:
|
||||
refresh_token:
|
||||
example: <refresh-token>
|
||||
type: string
|
||||
required:
|
||||
- refresh_token
|
||||
type: object
|
||||
handlers.refreshToken:
|
||||
properties:
|
||||
access_token:
|
||||
example: <jwt-token>
|
||||
type: string
|
||||
refresh_token:
|
||||
example: <refresh-token>
|
||||
type: string
|
||||
required:
|
||||
- access_token
|
||||
- refresh_token
|
||||
type: object
|
||||
handlers.updateUserReq:
|
||||
properties:
|
||||
|
|
@ -905,6 +1035,75 @@ info:
|
|||
title: FortuneBet API
|
||||
version: "1.0"
|
||||
paths:
|
||||
/admin:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get all Admins
|
||||
parameters:
|
||||
- description: Page number
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: Page size
|
||||
in: query
|
||||
name: page_size
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Get all Admins
|
||||
tags:
|
||||
- admin
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create Admin
|
||||
parameters:
|
||||
- description: Create admin
|
||||
in: body
|
||||
name: manger
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.CreateAdminReq'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Create Admin
|
||||
tags:
|
||||
- admin
|
||||
/auth/login:
|
||||
post:
|
||||
consumes:
|
||||
|
|
@ -1516,6 +1715,11 @@ paths:
|
|||
- application/json
|
||||
description: Update cashier
|
||||
parameters:
|
||||
- description: Cashier ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Update cashier
|
||||
in: body
|
||||
name: cashier
|
||||
|
|
@ -1790,7 +1994,7 @@ paths:
|
|||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create Managers
|
||||
description: Create Manager
|
||||
parameters:
|
||||
- description: Create manager
|
||||
in: body
|
||||
|
|
@ -1817,7 +2021,7 @@ paths:
|
|||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Create Managers
|
||||
summary: Create Manager
|
||||
tags:
|
||||
- manager
|
||||
/managers/{id}:
|
||||
|
|
@ -2079,6 +2283,95 @@ paths:
|
|||
summary: Retrieve raw odds by Market ID
|
||||
tags:
|
||||
- prematch
|
||||
/referral/settings:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieves current referral settings (admin only)
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ReferralSettings'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Get referral settings
|
||||
tags:
|
||||
- referral
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Updates referral settings (admin only)
|
||||
parameters:
|
||||
- description: Referral settings
|
||||
in: body
|
||||
name: settings
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ReferralSettings'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Update referral settings
|
||||
tags:
|
||||
- referral
|
||||
/referral/stats:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieves referral statistics for the authenticated user
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ReferralStats'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Get referral statistics
|
||||
tags:
|
||||
- referral
|
||||
/search/branch:
|
||||
get:
|
||||
consumes:
|
||||
|
|
@ -2110,6 +2403,31 @@ paths:
|
|||
summary: Search branches
|
||||
tags:
|
||||
- branch
|
||||
/search/company:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Gets all companies
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/handlers.CompanyRes'
|
||||
type: array
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Gets all companies
|
||||
tags:
|
||||
- company
|
||||
/supportedOperation:
|
||||
get:
|
||||
consumes:
|
||||
|
|
@ -2333,7 +2651,7 @@ paths:
|
|||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Updates the cashed out field
|
||||
description: Updates the verified status of a transaction
|
||||
parameters:
|
||||
- description: Transaction ID
|
||||
in: path
|
||||
|
|
@ -2342,7 +2660,7 @@ paths:
|
|||
type: integer
|
||||
- description: Updates Transaction Verification
|
||||
in: body
|
||||
name: updateCashOut
|
||||
name: updateVerified
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.UpdateTransactionVerifiedReq'
|
||||
|
|
@ -2361,7 +2679,7 @@ paths:
|
|||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Updates the cashed out field
|
||||
summary: Updates the verified field of a transaction
|
||||
tags:
|
||||
- transaction
|
||||
/transfer/refill/:id:
|
||||
|
|
@ -2659,6 +2977,39 @@ paths:
|
|||
summary: Send reset code
|
||||
tags:
|
||||
- user
|
||||
/user/single/{id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get a single user by id
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Get user by id
|
||||
tags:
|
||||
- user
|
||||
/user/wallet:
|
||||
get:
|
||||
consumes:
|
||||
|
|
@ -2690,6 +3041,72 @@ paths:
|
|||
summary: Get customer wallet
|
||||
tags:
|
||||
- wallet
|
||||
/virtual-game/callback:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Processes callbacks from PopOK for game events
|
||||
parameters:
|
||||
- description: Callback data
|
||||
in: body
|
||||
name: callback
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/domain.PopOKCallback'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
summary: Handle PopOK game callback
|
||||
tags:
|
||||
- virtual-game
|
||||
/virtual-game/launch:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Generates a URL to launch a PopOK game
|
||||
parameters:
|
||||
- description: Game launch details
|
||||
in: body
|
||||
name: launch
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.launchVirtualGameReq'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.launchVirtualGameRes'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Launch a PopOK virtual game
|
||||
tags:
|
||||
- virtual-game
|
||||
/wallet:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ func (q *Queries) CreateRefreshToken(ctx context.Context, arg CreateRefreshToken
|
|||
}
|
||||
|
||||
const GetRefreshToken = `-- name: GetRefreshToken :one
|
||||
SELECT id, user_id, token, expires_at, created_at, revoked FROM refresh_tokens
|
||||
SELECT id, user_id, token, expires_at, created_at, revoked
|
||||
FROM refresh_tokens
|
||||
WHERE token = $1
|
||||
`
|
||||
|
||||
|
|
@ -54,9 +55,31 @@ func (q *Queries) GetRefreshToken(ctx context.Context, token string) (RefreshTok
|
|||
return i, err
|
||||
}
|
||||
|
||||
const GetRefreshTokenByUserID = `-- name: GetRefreshTokenByUserID :one
|
||||
SELECT id, user_id, token, expires_at, created_at, revoked
|
||||
FROM refresh_tokens
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRefreshTokenByUserID(ctx context.Context, userID int64) (RefreshToken, error) {
|
||||
row := q.db.QueryRow(ctx, GetRefreshTokenByUserID, userID)
|
||||
var i RefreshToken
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.Token,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
&i.Revoked,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetUserByEmailPhone = `-- name: GetUserByEmailPhone :one
|
||||
SELECT id, first_name, last_name, email, phone_number, role, password, email_verified, phone_verified, created_at, updated_at, suspended_at, suspended, referral_code, referred_by FROM users
|
||||
WHERE email = $1 OR phone_number = $2
|
||||
SELECT id, first_name, last_name, email, phone_number, role, password, email_verified, phone_verified, created_at, updated_at, company_id, suspended_at, suspended, referral_code, referred_by
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
OR phone_number = $2
|
||||
`
|
||||
|
||||
type GetUserByEmailPhoneParams struct {
|
||||
|
|
@ -79,6 +102,7 @@ func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPho
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CompanyID,
|
||||
&i.SuspendedAt,
|
||||
&i.Suspended,
|
||||
&i.ReferralCode,
|
||||
|
|
@ -88,8 +112,8 @@ func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPho
|
|||
}
|
||||
|
||||
const RevokeRefreshToken = `-- name: RevokeRefreshToken :exec
|
||||
UPDATE refresh_tokens
|
||||
SET revoked = TRUE
|
||||
UPDATE refresh_tokens
|
||||
SET revoked = TRUE
|
||||
WHERE token = $1
|
||||
`
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ func (q *Queries) GetAllBranches(ctx context.Context) ([]BranchDetail, error) {
|
|||
}
|
||||
|
||||
const GetAllCashiers = `-- name: GetAllCashiers :many
|
||||
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.suspended_at, users.suspended, users.referral_code, users.referred_by
|
||||
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by
|
||||
FROM branch_cashiers
|
||||
JOIN users ON branch_cashiers.user_id = users.id
|
||||
`
|
||||
|
|
@ -217,6 +217,7 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]User, error) {
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CompanyID,
|
||||
&i.SuspendedAt,
|
||||
&i.Suspended,
|
||||
&i.ReferralCode,
|
||||
|
|
@ -430,7 +431,7 @@ func (q *Queries) GetBranchOperations(ctx context.Context, branchID int64) ([]Ge
|
|||
}
|
||||
|
||||
const GetCashiersByBranch = `-- name: GetCashiersByBranch :many
|
||||
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.suspended_at, users.suspended, users.referral_code, users.referred_by
|
||||
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by
|
||||
FROM branch_cashiers
|
||||
JOIN users ON branch_cashiers.user_id = users.id
|
||||
WHERE branch_cashiers.branch_id = $1
|
||||
|
|
@ -457,6 +458,7 @@ func (q *Queries) GetCashiersByBranch(ctx context.Context, branchID int64) ([]Us
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CompanyID,
|
||||
&i.SuspendedAt,
|
||||
&i.Suspended,
|
||||
&i.ReferralCode,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ package dbgen
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const CreateCompany = `-- name: CreateCompany :one
|
||||
|
|
@ -95,6 +97,37 @@ func (q *Queries) GetCompanyByID(ctx context.Context, id int64) (Company, error)
|
|||
return i, err
|
||||
}
|
||||
|
||||
const SearchCompanyByName = `-- name: SearchCompanyByName :many
|
||||
SELECT id, name, admin_id, wallet_id
|
||||
FROM companies
|
||||
WHERE name ILIKE '%' || $1 || '%'
|
||||
`
|
||||
|
||||
func (q *Queries) SearchCompanyByName(ctx context.Context, dollar_1 pgtype.Text) ([]Company, error) {
|
||||
rows, err := q.db.Query(ctx, SearchCompanyByName, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Company
|
||||
for rows.Next() {
|
||||
var i Company
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.AdminID,
|
||||
&i.WalletID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const UpdateCompany = `-- name: UpdateCompany :one
|
||||
UPDATE companies
|
||||
SET name = $1,
|
||||
|
|
|
|||
|
|
@ -310,23 +310,24 @@ type TicketWithOutcome struct {
|
|||
}
|
||||
|
||||
type Transaction struct {
|
||||
ID int64 `json:"id"`
|
||||
Amount int64 `json:"amount"`
|
||||
BranchID int64 `json:"branch_id"`
|
||||
CashierID int64 `json:"cashier_id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
Type int64 `json:"type"`
|
||||
PaymentOption int64 `json:"payment_option"`
|
||||
FullName string `json:"full_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
Amount int64 `json:"amount"`
|
||||
BranchID int64 `json:"branch_id"`
|
||||
CashierID int64 `json:"cashier_id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
Type int64 `json:"type"`
|
||||
PaymentOption int64 `json:"payment_option"`
|
||||
FullName string `json:"full_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
|
@ -341,6 +342,7 @@ type User struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
ReferralCode pgtype.Text `json:"referral_code"`
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
const CreateTransaction = `-- name: CreateTransaction :one
|
||||
INSERT INTO transactions (amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING id, amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at
|
||||
INSERT INTO transactions (amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateTransactionParams struct {
|
||||
|
|
@ -52,6 +52,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
|
|||
&i.BranchID,
|
||||
&i.CashierID,
|
||||
&i.BetID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.Type,
|
||||
&i.PaymentOption,
|
||||
&i.FullName,
|
||||
|
|
@ -69,7 +70,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
|
|||
}
|
||||
|
||||
const GetAllTransactions = `-- name: GetAllTransactions :many
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error) {
|
||||
|
|
@ -87,6 +88,7 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
|
|||
&i.BranchID,
|
||||
&i.CashierID,
|
||||
&i.BetID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.Type,
|
||||
&i.PaymentOption,
|
||||
&i.FullName,
|
||||
|
|
@ -111,7 +113,7 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
|
|||
}
|
||||
|
||||
const GetTransactionByBranch = `-- name: GetTransactionByBranch :many
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE branch_id = $1
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE branch_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([]Transaction, error) {
|
||||
|
|
@ -129,6 +131,7 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
|
|||
&i.BranchID,
|
||||
&i.CashierID,
|
||||
&i.BetID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.Type,
|
||||
&i.PaymentOption,
|
||||
&i.FullName,
|
||||
|
|
@ -153,7 +156,7 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
|
|||
}
|
||||
|
||||
const GetTransactionByID = `-- name: GetTransactionByID :one
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE id = $1
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction, error) {
|
||||
|
|
@ -165,6 +168,7 @@ func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction
|
|||
&i.BranchID,
|
||||
&i.CashierID,
|
||||
&i.BetID,
|
||||
&i.NumberOfOutcomes,
|
||||
&i.Type,
|
||||
&i.PaymentOption,
|
||||
&i.FullName,
|
||||
|
|
|
|||
|
|
@ -54,9 +54,24 @@ INSERT INTO users (
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
RETURNING id,
|
||||
first_name,
|
||||
last_name,
|
||||
|
|
@ -66,7 +81,9 @@ RETURNING id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
company_id
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
|
|
@ -80,6 +97,8 @@ type CreateUserParams struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
type CreateUserRow struct {
|
||||
|
|
@ -93,6 +112,8 @@ type CreateUserRow struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateUserRow, error) {
|
||||
|
|
@ -107,6 +128,8 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
|
|||
arg.PhoneVerified,
|
||||
arg.CreatedAt,
|
||||
arg.UpdatedAt,
|
||||
arg.Suspended,
|
||||
arg.CompanyID,
|
||||
)
|
||||
var i CreateUserRow
|
||||
err := row.Scan(
|
||||
|
|
@ -120,6 +143,8 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Suspended,
|
||||
&i.CompanyID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -144,10 +169,29 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
wHERE (
|
||||
role = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
LIMIT $3 OFFSET $4
|
||||
`
|
||||
|
||||
type GetAllUsersParams struct {
|
||||
Role string `json:"role"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type GetAllUsersRow struct {
|
||||
ID int64 `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
|
|
@ -159,10 +203,18 @@ type GetAllUsersRow struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllUsers(ctx context.Context) ([]GetAllUsersRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetAllUsers)
|
||||
func (q *Queries) GetAllUsers(ctx context.Context, arg GetAllUsersParams) ([]GetAllUsersRow, error) {
|
||||
rows, err := q.db.Query(ctx, GetAllUsers,
|
||||
arg.Role,
|
||||
arg.CompanyID,
|
||||
arg.Limit,
|
||||
arg.Offset,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -181,6 +233,9 @@ func (q *Queries) GetAllUsers(ctx context.Context) ([]GetAllUsersRow, error) {
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Suspended,
|
||||
&i.SuspendedAt,
|
||||
&i.CompanyID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -192,6 +247,31 @@ func (q *Queries) GetAllUsers(ctx context.Context) ([]GetAllUsersRow, error) {
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetTotalUsers = `-- name: GetTotalUsers :one
|
||||
SELECT COUNT(*)
|
||||
FROM users
|
||||
wHERE (
|
||||
role = $1
|
||||
OR $1 IS NULL
|
||||
)
|
||||
AND (
|
||||
company_id = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetTotalUsersParams struct {
|
||||
Role string `json:"role"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTotalUsers(ctx context.Context, arg GetTotalUsersParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetTotalUsers, arg.Role, arg.CompanyID)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const GetUserByEmail = `-- name: GetUserByEmail :one
|
||||
SELECT id,
|
||||
first_name,
|
||||
|
|
@ -202,7 +282,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
`
|
||||
|
|
@ -218,6 +301,9 @@ type GetUserByEmailRow struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetUserByEmail(ctx context.Context, email pgtype.Text) (GetUserByEmailRow, error) {
|
||||
|
|
@ -234,12 +320,15 @@ func (q *Queries) GetUserByEmail(ctx context.Context, email pgtype.Text) (GetUse
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Suspended,
|
||||
&i.SuspendedAt,
|
||||
&i.CompanyID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetUserByID = `-- name: GetUserByID :one
|
||||
SELECT id, first_name, last_name, email, phone_number, role, password, email_verified, phone_verified, created_at, updated_at, suspended_at, suspended, referral_code, referred_by
|
||||
SELECT id, first_name, last_name, email, phone_number, role, password, email_verified, phone_verified, created_at, updated_at, company_id, suspended_at, suspended, referral_code, referred_by
|
||||
FROM users
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -259,6 +348,7 @@ func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CompanyID,
|
||||
&i.SuspendedAt,
|
||||
&i.Suspended,
|
||||
&i.ReferralCode,
|
||||
|
|
@ -277,7 +367,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE phone_number = $1
|
||||
`
|
||||
|
|
@ -293,6 +386,9 @@ type GetUserByPhoneRow struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetUserByPhone(ctx context.Context, phoneNumber pgtype.Text) (GetUserByPhoneRow, error) {
|
||||
|
|
@ -309,6 +405,9 @@ func (q *Queries) GetUserByPhone(ctx context.Context, phoneNumber pgtype.Text) (
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Suspended,
|
||||
&i.SuspendedAt,
|
||||
&i.CompanyID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -323,7 +422,10 @@ SELECT id,
|
|||
email_verified,
|
||||
phone_verified,
|
||||
created_at,
|
||||
updated_at
|
||||
updated_at,
|
||||
suspended,
|
||||
suspended_at,
|
||||
company_id
|
||||
FROM users
|
||||
WHERE first_name ILIKE '%' || $1 || '%'
|
||||
OR last_name ILIKE '%' || $1 || '%'
|
||||
|
|
@ -341,6 +443,9 @@ type SearchUserByNameOrPhoneRow struct {
|
|||
PhoneVerified bool `json:"phone_verified"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, dollar_1 pgtype.Text) ([]SearchUserByNameOrPhoneRow, error) {
|
||||
|
|
@ -363,6 +468,9 @@ func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, dollar_1 pgtype.T
|
|||
&i.PhoneVerified,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Suspended,
|
||||
&i.SuspendedAt,
|
||||
&i.CompanyID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -374,6 +482,25 @@ func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, dollar_1 pgtype.T
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const SuspendUser = `-- name: SuspendUser :exec
|
||||
UPDATE users
|
||||
SET suspended = $1,
|
||||
suspended_at = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $3
|
||||
`
|
||||
|
||||
type SuspendUserParams struct {
|
||||
Suspended bool `json:"suspended"`
|
||||
SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) SuspendUser(ctx context.Context, arg SuspendUserParams) error {
|
||||
_, err := q.db.Exec(ctx, SuspendUser, arg.Suspended, arg.SuspendedAt, arg.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdatePassword = `-- name: UpdatePassword :exec
|
||||
UPDATE users
|
||||
SET password = $1,
|
||||
|
|
|
|||
5
go.mod
5
go.mod
|
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/fasthttp/websocket v1.5.3 // indirect
|
||||
github.com/fasthttp/websocket v1.5.8 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
|
|
@ -31,6 +31,7 @@ require (
|
|||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/gofiber/contrib/websocket v1.3.4
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
|
|
@ -44,7 +45,7 @@ require (
|
|||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
||||
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -24,6 +24,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fasthttp/websocket v1.5.3 h1:TPpQuLwJYfd4LJPXvHDYPMFWbLjsT91n3GpWtCQtdek=
|
||||
github.com/fasthttp/websocket v1.5.3/go.mod h1:46gg/UBmTU1kUaTcwQXpUxtRwG2PvIZYeA8oL6vF3Fs=
|
||||
github.com/fasthttp/websocket v1.5.8 h1:k5DpirKkftIF/w1R8ZzjSgARJrs54Je9YJK37DL/Ah8=
|
||||
github.com/fasthttp/websocket v1.5.8/go.mod h1:d08g8WaT6nnyvg9uMm8K9zMYyDjfKyj3170AtPRuVU0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
|
@ -49,6 +51,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/gofiber/contrib/websocket v1.3.4 h1:tWeBdbJ8q0WFQXariLN4dBIbGH9KBU75s0s7YXplOSg=
|
||||
github.com/gofiber/contrib/websocket v1.3.4/go.mod h1:kTFBPC6YENCnKfKx0BoOFjgXxdz7E85/STdkmZPEmPs=
|
||||
github.com/gofiber/fiber/v2 v2.32.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
|
|
@ -116,6 +120,8 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
|
|||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
|
|
|
|||
|
|
@ -19,15 +19,16 @@ const (
|
|||
// Transaction only represents when the user cashes out a bet in the shop
|
||||
// It probably would be better to call it a CashOut or ShopWithdrawal
|
||||
type Transaction struct {
|
||||
ID int64
|
||||
Amount Currency
|
||||
BranchID int64
|
||||
CashierID int64
|
||||
BetID int64
|
||||
Type TransactionType
|
||||
PaymentOption PaymentOption
|
||||
FullName string
|
||||
PhoneNumber string
|
||||
ID int64
|
||||
Amount Currency
|
||||
BranchID int64
|
||||
CashierID int64
|
||||
BetID int64
|
||||
NumberOfOutcomes int64
|
||||
Type TransactionType
|
||||
PaymentOption PaymentOption
|
||||
FullName string
|
||||
PhoneNumber string
|
||||
// Payment Details for bank
|
||||
BankCode string
|
||||
BeneficiaryName string
|
||||
|
|
@ -38,14 +39,15 @@ type Transaction struct {
|
|||
}
|
||||
|
||||
type CreateTransaction struct {
|
||||
Amount Currency
|
||||
BranchID int64
|
||||
CashierID int64
|
||||
BetID int64
|
||||
Type TransactionType
|
||||
PaymentOption PaymentOption
|
||||
FullName string
|
||||
PhoneNumber string
|
||||
Amount Currency
|
||||
BranchID int64
|
||||
CashierID int64
|
||||
BetID int64
|
||||
NumberOfOutcomes int64
|
||||
Type TransactionType
|
||||
PaymentOption PaymentOption
|
||||
FullName string
|
||||
PhoneNumber string
|
||||
// Payment Details for bank
|
||||
BankCode string
|
||||
BeneficiaryName string
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@ type User struct {
|
|||
SuspendedAt time.Time
|
||||
Suspended bool
|
||||
//
|
||||
BranchID int64
|
||||
CompanyID ValidInt64
|
||||
}
|
||||
type RegisterUserReq struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
Email string
|
||||
PhoneNumber string
|
||||
Password string
|
||||
Role string
|
||||
FirstName string
|
||||
LastName string
|
||||
Email string
|
||||
PhoneNumber string
|
||||
Password string
|
||||
Role string
|
||||
Otp string
|
||||
ReferralCode string `json:"referral_code"`
|
||||
OtpMedium OtpMedium
|
||||
|
|
@ -47,6 +47,8 @@ type CreateUserReq struct {
|
|||
PhoneNumber string
|
||||
Password string
|
||||
Role string
|
||||
Suspended bool
|
||||
CompanyID ValidInt64
|
||||
}
|
||||
type ResetPasswordReq struct {
|
||||
Email string
|
||||
|
|
|
|||
|
|
@ -29,13 +29,23 @@ func (s *Store) GetUserByEmailPhone(ctx context.Context, email, phone string) (d
|
|||
return domain.User{}, err
|
||||
}
|
||||
return domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Password: user.Password,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Password: user.Password,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
CompanyID: domain.ValidInt64{
|
||||
Value: user.CompanyID.Int64,
|
||||
Valid: user.CompanyID.Valid,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
|
@ -72,6 +82,25 @@ func (s *Store) GetRefreshToken(ctx context.Context, token string) (domain.Refre
|
|||
Revoked: rf.Revoked,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetRefreshTokenByUserID(ctx context.Context, id int64) (domain.RefreshToken, error) {
|
||||
rf, err := s.queries.GetRefreshTokenByUserID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return domain.RefreshToken{}, authentication.ErrRefreshTokenNotFound
|
||||
}
|
||||
return domain.RefreshToken{}, err
|
||||
}
|
||||
|
||||
return domain.RefreshToken{
|
||||
Token: rf.Token,
|
||||
UserID: rf.UserID,
|
||||
CreatedAt: rf.CreatedAt.Time,
|
||||
ExpiresAt: rf.ExpiresAt.Time,
|
||||
Revoked: rf.Revoked,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) RevokeRefreshToken(ctx context.Context, token string) error {
|
||||
return s.queries.RevokeRefreshToken(ctx, token)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func convertCreateCompany(company domain.CreateCompany) dbgen.CreateCompanyParams {
|
||||
|
|
@ -46,6 +47,23 @@ func (s *Store) GetAllCompanies(ctx context.Context) ([]domain.Company, error) {
|
|||
return companies, nil
|
||||
}
|
||||
|
||||
func (s *Store) SearchCompanyByName(ctx context.Context, name string) ([]domain.Company, error) {
|
||||
dbCompanies, err := s.queries.SearchCompanyByName(ctx, pgtype.Text{
|
||||
String: name,
|
||||
Valid: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var companies []domain.Company = make([]domain.Company, 0, len(dbCompanies))
|
||||
|
||||
for _, dbCompany := range dbCompanies {
|
||||
companies = append(companies, convertDBCompany(dbCompany))
|
||||
}
|
||||
return companies, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetCompanyByID(ctx context.Context, id int64) (domain.Company, error) {
|
||||
dbCompany, err := s.queries.GetCompanyByID(ctx, id)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,20 @@ import (
|
|||
|
||||
func convertDBTransaction(transaction dbgen.Transaction) domain.Transaction {
|
||||
return domain.Transaction{
|
||||
Amount: domain.Currency(transaction.Amount),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
Type: domain.TransactionType(transaction.Type),
|
||||
PaymentOption: domain.PaymentOption(transaction.PaymentOption),
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
Amount: domain.Currency(transaction.Amount),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
NumberOfOutcomes: transaction.NumberOfOutcomes,
|
||||
Type: domain.TransactionType(transaction.Type),
|
||||
PaymentOption: domain.PaymentOption(transaction.PaymentOption),
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func (s *Store) CreateUser(ctx context.Context, user domain.User, usedOtpId int64) (domain.User, error) {
|
||||
func (s *Store) CreateUser(ctx context.Context, user domain.User, usedOtpId int64, is_company bool) (domain.User, error) {
|
||||
err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{
|
||||
ID: usedOtpId,
|
||||
UsedAt: pgtype.Timestamptz{
|
||||
|
|
@ -83,23 +83,44 @@ func (s *Store) GetUserByID(ctx context.Context, id int64) (domain.User, error)
|
|||
Suspended: user.Suspended,
|
||||
}, nil
|
||||
}
|
||||
func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, error) {
|
||||
users, err := s.queries.GetAllUsers(ctx)
|
||||
func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, int64, error) {
|
||||
users, err := s.queries.GetAllUsers(ctx, dbgen.GetAllUsersParams{
|
||||
Role: filter.Role,
|
||||
CompanyID: pgtype.Int8{
|
||||
Int64: filter.CompanyID.Value,
|
||||
Valid: filter.CompanyID.Valid,
|
||||
},
|
||||
Limit: int32(filter.PageSize),
|
||||
Offset: int32(filter.Page),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
userList := make([]domain.User, len(users))
|
||||
for i, user := range users {
|
||||
userList[i] = domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
}
|
||||
}
|
||||
return userList, nil
|
||||
totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{
|
||||
Role: filter.Role,
|
||||
CompanyID: pgtype.Int8{
|
||||
Int64: filter.CompanyID.Value,
|
||||
Valid: filter.CompanyID.Valid,
|
||||
},
|
||||
})
|
||||
return userList, totalCount, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.User, error) {
|
||||
|
|
@ -110,12 +131,18 @@ func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.User, error) {
|
|||
userList := make([]domain.User, len(users))
|
||||
for i, user := range users {
|
||||
userList[i] = domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
}
|
||||
}
|
||||
return userList, nil
|
||||
|
|
@ -129,12 +156,18 @@ func (s *Store) GetCashiersByBranch(ctx context.Context, branchID int64) ([]doma
|
|||
userList := make([]domain.User, len(users))
|
||||
for i, user := range users {
|
||||
userList[i] = domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
}
|
||||
}
|
||||
return userList, nil
|
||||
|
|
@ -152,12 +185,18 @@ func (s *Store) SearchUserByNameOrPhone(ctx context.Context, searchString string
|
|||
userList := make([]domain.User, 0, len(users))
|
||||
for _, user := range users {
|
||||
userList = append(userList, domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
})
|
||||
}
|
||||
return userList, nil
|
||||
|
|
@ -216,12 +255,18 @@ func (s *Store) GetUserByEmail(ctx context.Context, email string) (domain.User,
|
|||
return domain.User{}, err
|
||||
}
|
||||
return domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
}, nil
|
||||
}
|
||||
func (s *Store) GetUserByPhone(ctx context.Context, phoneNum string) (domain.User, error) {
|
||||
|
|
@ -235,13 +280,20 @@ func (s *Store) GetUserByPhone(ctx context.Context, phoneNum string) (domain.Use
|
|||
}
|
||||
return domain.User{}, err
|
||||
}
|
||||
|
||||
return domain.User{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
Email: user.Email.String,
|
||||
PhoneNumber: user.PhoneNumber.String,
|
||||
Role: domain.Role(user.Role),
|
||||
EmailVerified: user.EmailVerified,
|
||||
PhoneVerified: user.PhoneVerified,
|
||||
CreatedAt: user.CreatedAt.Time,
|
||||
UpdatedAt: user.UpdatedAt.Time,
|
||||
Suspended: user.Suspended,
|
||||
SuspendedAt: user.SuspendedAt.Time,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +324,7 @@ func (s *Store) UpdatePassword(ctx context.Context, identifier string, password
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.User) (domain.User, error) {
|
||||
func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error) {
|
||||
userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
|
|
@ -296,16 +348,26 @@ func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.User) (dom
|
|||
Time: time.Now(),
|
||||
Valid: true,
|
||||
},
|
||||
Suspended: user.Suspended,
|
||||
CompanyID: pgtype.Int8{
|
||||
Int64: user.CompanyID.Value,
|
||||
Valid: user.CompanyID.Valid,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
return domain.User{
|
||||
ID: userRes.ID,
|
||||
FirstName: userRes.FirstName,
|
||||
LastName: userRes.LastName,
|
||||
Email: userRes.Email.String,
|
||||
PhoneNumber: userRes.PhoneNumber.String,
|
||||
Role: domain.Role(userRes.Role),
|
||||
ID: userRes.ID,
|
||||
FirstName: userRes.FirstName,
|
||||
LastName: userRes.LastName,
|
||||
Email: userRes.Email.String,
|
||||
PhoneNumber: userRes.PhoneNumber.String,
|
||||
Role: domain.Role(userRes.Role),
|
||||
EmailVerified: userRes.EmailVerified,
|
||||
PhoneVerified: userRes.PhoneVerified,
|
||||
CreatedAt: userRes.CreatedAt.Time,
|
||||
UpdatedAt: userRes.UpdatedAt.Time,
|
||||
Suspended: userRes.Suspended,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ var (
|
|||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrExpiredToken = errors.New("token expired")
|
||||
ErrRefreshTokenNotFound = errors.New("refresh token not found") // i.e login again
|
||||
ErrUserSuspended = errors.New("user has been suspended")
|
||||
)
|
||||
|
||||
type LoginSuccess struct {
|
||||
UserId int64
|
||||
Role domain.Role
|
||||
RfToken string
|
||||
BranchId int64
|
||||
UserId int64
|
||||
Role domain.Role
|
||||
RfToken string
|
||||
CompanyID domain.ValidInt64
|
||||
}
|
||||
|
||||
func (s *Service) Login(ctx context.Context, email, phone string, password string) (LoginSuccess, error) {
|
||||
|
|
@ -34,6 +35,9 @@ func (s *Service) Login(ctx context.Context, email, phone string, password strin
|
|||
if err != nil {
|
||||
return LoginSuccess{}, err
|
||||
}
|
||||
if user.Suspended {
|
||||
return LoginSuccess{}, ErrUserSuspended
|
||||
}
|
||||
|
||||
refreshToken, err := generateRefreshToken()
|
||||
if err != nil {
|
||||
|
|
@ -49,24 +53,24 @@ func (s *Service) Login(ctx context.Context, email, phone string, password strin
|
|||
return LoginSuccess{}, err
|
||||
}
|
||||
return LoginSuccess{
|
||||
UserId: user.ID,
|
||||
Role: user.Role,
|
||||
RfToken: refreshToken,
|
||||
BranchId: user.BranchID,
|
||||
UserId: user.ID,
|
||||
Role: user.Role,
|
||||
RfToken: refreshToken,
|
||||
CompanyID: user.CompanyID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) RefreshToken(ctx context.Context, refToken string) error {
|
||||
func (s *Service) RefreshToken(ctx context.Context, refToken string) (domain.RefreshToken, error) {
|
||||
|
||||
token, err := s.tokenStore.GetRefreshToken(ctx, refToken)
|
||||
if err != nil {
|
||||
return err
|
||||
return domain.RefreshToken{}, err
|
||||
}
|
||||
if token.Revoked {
|
||||
return ErrRefreshTokenNotFound
|
||||
return domain.RefreshToken{}, ErrRefreshTokenNotFound
|
||||
}
|
||||
if token.ExpiresAt.Before(time.Now()) {
|
||||
return ErrExpiredToken
|
||||
return domain.RefreshToken{}, ErrExpiredToken
|
||||
}
|
||||
|
||||
// newRefToken, err := generateRefreshToken()
|
||||
|
|
@ -80,8 +84,19 @@ func (s *Service) RefreshToken(ctx context.Context, refToken string) error {
|
|||
// CreatedAt: time.Now(),
|
||||
// ExpiresAt: time.Now().Add(time.Duration(s.RefreshExpiry) * time.Second),
|
||||
// })
|
||||
return nil
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetLastLogin(ctx context.Context, user_id int64) (*time.Time, error) {
|
||||
refreshToken, err := s.tokenStore.GetRefreshTokenByUserID(ctx, user_id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &refreshToken.CreatedAt, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Service) Logout(ctx context.Context, refToken string) error {
|
||||
token, err := s.tokenStore.GetRefreshToken(ctx, refToken)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ type UserStore interface {
|
|||
type TokenStore interface {
|
||||
CreateRefreshToken(ctx context.Context, rt domain.RefreshToken) error
|
||||
GetRefreshToken(ctx context.Context, token string) (domain.RefreshToken, error)
|
||||
GetRefreshTokenByUserID(ctx context.Context, id int64) (domain.RefreshToken, error)
|
||||
RevokeRefreshToken(ctx context.Context, token string) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package bet
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
|
@ -16,6 +18,21 @@ func NewService(betStore BetStore) *Service {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Service) GenerateCashoutID() (string, error) {
|
||||
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
const length int = 13
|
||||
charLen := big.NewInt(int64(len(chars)))
|
||||
result := make([]byte, length)
|
||||
for i := 0; i < length; i++ {
|
||||
index, err := rand.Int(rand.Reader, charLen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result[i] = chars[index.Int64()]
|
||||
}
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error) {
|
||||
|
||||
return s.betStore.CreateBet(ctx, bet)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ type CompanyStore interface {
|
|||
CreateCompany(ctx context.Context, company domain.CreateCompany) (domain.Company, error)
|
||||
GetAllCompanies(ctx context.Context) ([]domain.Company, error)
|
||||
GetCompanyByID(ctx context.Context, id int64) (domain.Company, error)
|
||||
SearchCompanyByName(ctx context.Context, name string) ([]domain.Company, error)
|
||||
UpdateCompany(ctx context.Context, id int64, company domain.UpdateCompany) (domain.Company, error)
|
||||
DeleteCompany(ctx context.Context, id int64) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ func (s *Service) GetCompanyByID(ctx context.Context, id int64) (domain.Company,
|
|||
return s.companyStore.GetCompanyByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) SearchCompanyByName(ctx context.Context, name string) ([]domain.Company, error) {
|
||||
return s.companyStore.SearchCompanyByName(ctx, name)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateCompany(ctx context.Context, id int64, company domain.UpdateCompany) (domain.Company, error) {
|
||||
return s.companyStore.UpdateCompany(ctx, id, company)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
||||
func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq) (domain.User, error) {
|
||||
func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq, is_company bool) (domain.User, error) {
|
||||
// Create User
|
||||
// creator, err := s.userStore.GetUserByID(ctx, createrUserId)
|
||||
// if err != nil {
|
||||
|
|
@ -33,7 +33,9 @@ func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq) (do
|
|||
Role: domain.Role(User.Role),
|
||||
EmailVerified: true,
|
||||
PhoneVerified: true,
|
||||
})
|
||||
Suspended: User.Suspended,
|
||||
CompanyID: User.CompanyID,
|
||||
}, is_company)
|
||||
}
|
||||
|
||||
func (s *Service) DeleteUser(ctx context.Context, id int64) error {
|
||||
|
|
@ -42,10 +44,10 @@ func (s *Service) DeleteUser(ctx context.Context, id int64) error {
|
|||
}
|
||||
|
||||
type Filter struct {
|
||||
Role string
|
||||
BranchId ValidBranchId
|
||||
Page int
|
||||
PageSize int
|
||||
Role string
|
||||
CompanyID domain.ValidInt64
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
type ValidRole struct {
|
||||
Value domain.Role
|
||||
|
|
@ -56,7 +58,7 @@ type ValidBranchId struct {
|
|||
Valid bool
|
||||
}
|
||||
|
||||
func (s *Service) GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, error) {
|
||||
func (s *Service) GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, int64, error) {
|
||||
// Get all Users
|
||||
return s.userStore.GetAllUsers(ctx, filter)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import (
|
|||
)
|
||||
|
||||
type UserStore interface {
|
||||
CreateUser(ctx context.Context, user domain.User, usedOtpId int64) (domain.User, error)
|
||||
CreateUserWithoutOtp(ctx context.Context, user domain.User) (domain.User, error)
|
||||
CreateUser(ctx context.Context, user domain.User, usedOtpId int64, is_company bool) (domain.User, error)
|
||||
CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error)
|
||||
GetUserByID(ctx context.Context, id int64) (domain.User, error)
|
||||
GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, error)
|
||||
GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, int64, error)
|
||||
GetAllCashiers(ctx context.Context) ([]domain.User, error)
|
||||
GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error)
|
||||
UpdateUser(ctx context.Context, user domain.UpdateUserReq) error
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterU
|
|||
PhoneVerified: registerReq.OtpMedium == domain.OtpMediumSms,
|
||||
}
|
||||
// create the user and mark otp as used
|
||||
user, err := s.userStore.CreateUser(ctx, userR, otp.ID)
|
||||
user, err := s.userStore.CreateUser(ctx, userR, otp.ID, false)
|
||||
if err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import (
|
|||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
|
|
|
|||
156
internal/web_server/handlers/admin.go
Normal file
156
internal/web_server/handlers/admin.go
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type CreateAdminReq 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,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
// CreateAdmin godoc
|
||||
// @Summary Create Admin
|
||||
// @Description Create Admin
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param manger body CreateAdminReq true "Create admin"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin [post]
|
||||
func (h *Handler) CreateAdmin(c *fiber.Ctx) error {
|
||||
var companyID domain.ValidInt64
|
||||
var req CreateAdminReq
|
||||
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, req)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
// Admins can be created without company ids and can be assigned later
|
||||
if req.CompanyID == nil {
|
||||
companyID = domain.ValidInt64{
|
||||
Value: 0,
|
||||
Valid: false,
|
||||
}
|
||||
} else {
|
||||
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.RoleAdmin),
|
||||
CompanyID: companyID,
|
||||
}
|
||||
_, err := h.userSvc.CreateUser(c.Context(), user, true)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateAdmin failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create admin", nil, nil)
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Admin created successfully", nil, nil)
|
||||
}
|
||||
|
||||
type AdminRes 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 /admin [get]
|
||||
func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
|
||||
filter := user.Filter{
|
||||
Role: string(domain.RoleAdmin),
|
||||
CompanyID: domain.ValidInt64{
|
||||
Value: int64(c.QueryInt("company_id")),
|
||||
Valid: true,
|
||||
},
|
||||
Page: c.QueryInt("page", 1) - 1,
|
||||
PageSize: c.QueryInt("page_size", 10),
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
admins, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllAdmins failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Admins", nil, nil)
|
||||
}
|
||||
|
||||
var result []AdminRes = make([]AdminRes, len(admins))
|
||||
for index, admin := range admins {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), admin.ID)
|
||||
if err != nil {
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &admin.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", admin.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
}
|
||||
result[index] = AdminRes{
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page, int(total))
|
||||
|
||||
}
|
||||
|
|
@ -3,13 +3,22 @@ package handlers
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type loginCustomerReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
Password string `json:"password" validate:"required" example:"password123"`
|
||||
}
|
||||
type loginCustomerRes struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
// LoginCustomer godoc
|
||||
// @Summary Login customer
|
||||
|
|
@ -24,16 +33,6 @@ import (
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/login [post]
|
||||
func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
||||
type loginCustomerReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
Password string `json:"password" validate:"required" example:"password123"`
|
||||
}
|
||||
type loginCustomerRes struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
var req loginCustomerReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -51,13 +50,15 @@ func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
|||
switch {
|
||||
case errors.Is(err, authentication.ErrInvalidPassword), errors.Is(err, authentication.ErrUserNotFound):
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
|
||||
case errors.Is(err, authentication.ErrUserSuspended):
|
||||
return fiber.NewError(fiber.StatusUnauthorized, "User login has been locked")
|
||||
default:
|
||||
h.logger.Error("Login failed", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Internal server error")
|
||||
}
|
||||
}
|
||||
|
||||
accessToken, err := jwtutil.CreateJwt(successRes.UserId, successRes.Role, successRes.BranchId, 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.logger.Error("Failed to create access token", "userID", successRes.UserId, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate access token")
|
||||
|
|
@ -71,6 +72,10 @@ func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Login successful", res, nil)
|
||||
}
|
||||
|
||||
type refreshToken struct {
|
||||
AccessToken string `json:"access_token" validate:"required" example:"<jwt-token>"`
|
||||
RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"`
|
||||
}
|
||||
|
||||
// RefreshToken godoc
|
||||
// @Summary Refresh token
|
||||
|
|
@ -85,16 +90,13 @@ func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/refresh [post]
|
||||
func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||||
type refreshTokenReq struct {
|
||||
AccessToken string `json:"access_token" validate:"required" example:"<jwt-token>"`
|
||||
RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"`
|
||||
}
|
||||
|
||||
type loginCustomerRes struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
var req refreshTokenReq
|
||||
var req refreshToken
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("Failed to parse RefreshToken request", "error", err)
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
|
|
@ -104,10 +106,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
userId := c.Locals("user_id").(int64)
|
||||
role := c.Locals("role").(string)
|
||||
branchId := c.Locals("branch_id").(int64)
|
||||
err := h.authSvc.RefreshToken(c.Context(), req.RefreshToken)
|
||||
refreshToken, err := h.authSvc.RefreshToken(c.Context(), req.RefreshToken)
|
||||
if err != nil {
|
||||
h.logger.Info("Refresh token attempt failed", "refreshToken", req.RefreshToken, "error", err)
|
||||
switch {
|
||||
|
|
@ -121,8 +120,10 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
}
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), refreshToken.UserID)
|
||||
|
||||
// Assuming the refreshed token includes userID and role info; adjust if needed
|
||||
accessToken, err := jwtutil.CreateJwt(userId, domain.Role(role), branchId, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
|
||||
accessToken, err := jwtutil.CreateJwt(user.ID, user.Role, user.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to create new access token", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate access token")
|
||||
|
|
@ -135,6 +136,10 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Refresh successful", res, nil)
|
||||
}
|
||||
|
||||
type logoutReq struct {
|
||||
RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"`
|
||||
}
|
||||
|
||||
// LogOutCustomer godoc
|
||||
// @Summary Logout customer
|
||||
// @Description Logout customer
|
||||
|
|
@ -148,9 +153,6 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /auth/logout [post]
|
||||
func (h *Handler) LogOutCustomer(c *fiber.Ctx) error {
|
||||
type logoutReq struct {
|
||||
RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"`
|
||||
}
|
||||
|
||||
var req logoutReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ package handlers
|
|||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CreateBetOutcomeReq struct {
|
||||
|
|
@ -24,7 +22,6 @@ type CreateBetReq struct {
|
|||
Status domain.OutcomeStatus `json:"status" example:"1"`
|
||||
FullName string `json:"full_name" example:"John"`
|
||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
IsShopBet bool `json:"is_shop_bet" example:"false"`
|
||||
}
|
||||
|
||||
type CreateBetRes struct {
|
||||
|
|
@ -117,7 +114,15 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
// Validating user by role
|
||||
// Differentiating between offline and online bets
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
cashoutUUID := uuid.New()
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, user id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
cashoutID, err := h.betSvc.GenerateCashoutID()
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, unable to create cashout id")
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid request", err, nil)
|
||||
}
|
||||
var bet domain.Bet
|
||||
if user.Role == domain.RoleCashier {
|
||||
|
||||
|
|
@ -153,8 +158,27 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
Value: userID,
|
||||
Valid: false,
|
||||
},
|
||||
IsShopBet: req.IsShopBet,
|
||||
CashoutID: cashoutUUID.String(),
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else if user.Role == domain.RoleSuperAdmin {
|
||||
// This is just for testing
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: req.TotalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: 1,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else {
|
||||
// TODO if user is customer, get id from the token then get the wallet id from there and reduce the amount
|
||||
|
|
@ -173,8 +197,8 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: req.IsShopBet,
|
||||
CashoutID: cashoutUUID.String(),
|
||||
IsShopBet: false,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -200,10 +224,10 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
// Checking to make sure the event hasn't already started
|
||||
currentTime := time.Now()
|
||||
if event.StartTime.Before(currentTime) {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
|
||||
}
|
||||
// currentTime := time.Now()
|
||||
// if event.StartTime.Before(currentTime) {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
|
||||
// }
|
||||
|
||||
odds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr)
|
||||
|
||||
|
|
@ -224,7 +248,7 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
rawBytes, err := json.Marshal(raw)
|
||||
err = json.Unmarshal(rawBytes, &rawOdd)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to unmarshal raw odd:", err)
|
||||
h.logger.Error("Failed to unmarshal raw odd", "error", err)
|
||||
continue
|
||||
}
|
||||
if rawOdd.ID == oddIDStr {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
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"
|
||||
)
|
||||
|
|
@ -16,6 +18,7 @@ type CreateCashierReq struct {
|
|||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
Password string `json:"password" example:"password123"`
|
||||
BranchID int64 `json:"branch_id" example:"1"`
|
||||
Suspended bool `json:"suspended" example:"false"`
|
||||
}
|
||||
|
||||
// CreateCashier godoc
|
||||
|
|
@ -31,6 +34,10 @@ type CreateCashierReq struct {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashiers [post]
|
||||
func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
||||
|
||||
// Get user_id from middleware
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
var req CreateCashierReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
|
|
@ -47,8 +54,11 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
|
|||
PhoneNumber: req.PhoneNumber,
|
||||
Password: req.Password,
|
||||
Role: string(domain.RoleCashier),
|
||||
Suspended: req.Suspended,
|
||||
CompanyID: companyID,
|
||||
}
|
||||
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest)
|
||||
fmt.Print(req.Suspended)
|
||||
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest, true)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
|
||||
|
|
@ -76,6 +86,7 @@ type GetCashierRes struct {
|
|||
UpdatedAt time.Time `json:"updated_at"`
|
||||
SuspendedAt time.Time `json:"suspended_at"`
|
||||
Suspended bool `json:"suspended"`
|
||||
LastLogin time.Time `json:"last_login"`
|
||||
}
|
||||
|
||||
// GetAllCashiers godoc
|
||||
|
|
@ -113,9 +124,19 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
||||
}
|
||||
|
||||
var result []GetCashierRes
|
||||
var result []GetCashierRes = make([]GetCashierRes, 0, len(cashiers))
|
||||
|
||||
for _, cashier := range cashiers {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), cashier.ID)
|
||||
if err != nil {
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &cashier.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", cashier.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, GetCashierRes{
|
||||
ID: cashier.ID,
|
||||
FirstName: cashier.FirstName,
|
||||
|
|
@ -129,6 +150,7 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
|
|||
UpdatedAt: cashier.UpdatedAt,
|
||||
SuspendedAt: cashier.SuspendedAt,
|
||||
Suspended: cashier.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -148,6 +170,7 @@ type updateUserReq struct {
|
|||
// @Tags cashier
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Cashier ID"
|
||||
// @Param cashier body updateUserReq true "Update cashier"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
|
|
@ -155,6 +178,12 @@ type updateUserReq struct {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /cashiers/{id} [put]
|
||||
func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
||||
cashierIdStr := c.Params("id")
|
||||
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
}
|
||||
var req updateUserReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
|
|
@ -166,12 +195,7 @@ func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
|
|||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
cashierIdStr := c.Params("id")
|
||||
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
}
|
||||
|
||||
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
|
||||
UserId: cashierId,
|
||||
FirstName: domain.ValidString{
|
||||
|
|
|
|||
|
|
@ -143,6 +143,37 @@ func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
|
||||
// GetAllCompanies godoc
|
||||
// @Summary Gets all companies
|
||||
// @Description Gets all companies
|
||||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} CompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /search/company [get]
|
||||
func (h *Handler) SearchCompany(c *fiber.Ctx) error {
|
||||
searchQuery := c.Query("q")
|
||||
if searchQuery == "" {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil)
|
||||
}
|
||||
companies, err := h.companySvc.SearchCompanyByName(c.Context(), searchQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get companies", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
|
||||
}
|
||||
|
||||
var result []CompanyRes = make([]CompanyRes, 0, len(companies))
|
||||
|
||||
for _, company := range companies {
|
||||
result = append(result, convertCompany(company))
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
|
||||
|
||||
}
|
||||
|
||||
// UpdateCompany godoc
|
||||
// @Summary Updates a company
|
||||
// @Description Updates a company
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ package handlers
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
|
@ -15,11 +17,12 @@ type CreateManagerReq struct {
|
|||
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,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
// CreateManagers godoc
|
||||
// @Summary Create Managers
|
||||
// @Description Create Managers
|
||||
// CreateManager godoc
|
||||
// @Summary Create Manager
|
||||
// @Description Create Manager
|
||||
// @Tags manager
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
|
|
@ -30,6 +33,9 @@ type CreateManagerReq struct {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /managers [post]
|
||||
func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
||||
|
||||
// Get user_id from middleware
|
||||
|
||||
var req CreateManagerReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("RegisterUser failed", "error", err)
|
||||
|
|
@ -39,6 +45,22 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
var companyID domain.ValidInt64
|
||||
role := c.Locals("role").(domain.Role)
|
||||
if role == domain.RoleSuperAdmin {
|
||||
if req.CompanyID == nil {
|
||||
h.logger.Error("RegisterUser failed error: company id is required")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", "Company ID is required", nil)
|
||||
}
|
||||
companyID = domain.ValidInt64{
|
||||
Value: *req.CompanyID,
|
||||
Valid: true,
|
||||
}
|
||||
} else {
|
||||
companyID = c.Locals("company_id").(domain.ValidInt64)
|
||||
}
|
||||
|
||||
user := domain.CreateUserReq{
|
||||
FirstName: req.FirstName,
|
||||
LastName: req.LastName,
|
||||
|
|
@ -46,16 +68,33 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
PhoneNumber: req.PhoneNumber,
|
||||
Password: req.Password,
|
||||
Role: string(domain.RoleBranchManager),
|
||||
CompanyID: companyID,
|
||||
}
|
||||
_, err := h.userSvc.CreateUser(c.Context(), user)
|
||||
_, err := h.userSvc.CreateUser(c.Context(), user, true)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateManagers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create Managers", nil, nil)
|
||||
h.logger.Error("CreateManager failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create manager", nil, nil)
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Managers created successfully", nil, nil)
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Manager created successfully", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
type ManagersRes 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"`
|
||||
}
|
||||
|
||||
// GetAllManagers godoc
|
||||
// @Summary Get all Managers
|
||||
// @Description Get all Managers
|
||||
|
|
@ -64,7 +103,7 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
// @Produce json
|
||||
// @Param page query int false "Page number"
|
||||
// @Param page_size query int false "Page size"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Success 200 {object} ManagersRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
|
|
@ -72,24 +111,52 @@ func (h *Handler) CreateManager(c *fiber.Ctx) error {
|
|||
func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
|
||||
filter := user.Filter{
|
||||
Role: string(domain.RoleBranchManager),
|
||||
BranchId: user.ValidBranchId{
|
||||
Value: int64(c.QueryInt("branch_id")),
|
||||
CompanyID: domain.ValidInt64{
|
||||
Value: int64(c.QueryInt("company_id")),
|
||||
Valid: true,
|
||||
},
|
||||
Page: c.QueryInt("page", 1),
|
||||
Page: c.QueryInt("page", 1) - 1,
|
||||
PageSize: c.QueryInt("page_size", 10),
|
||||
}
|
||||
valErrs, ok := h.validator.Validate(c, filter)
|
||||
if !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
Managers, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
managers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllManagers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", nil, nil)
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Managers retrieved successfully", Managers, nil)
|
||||
var result []ManagersRes = make([]ManagersRes, len(managers))
|
||||
for index, manager := range managers {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), manager.ID)
|
||||
if err != nil {
|
||||
if err == authentication.ErrRefreshTokenNotFound {
|
||||
lastLogin = &manager.CreatedAt
|
||||
} else {
|
||||
h.logger.Error("Failed to get user last login", "userID", manager.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
}
|
||||
result[index] = ManagersRes{
|
||||
ID: manager.ID,
|
||||
FirstName: manager.FirstName,
|
||||
LastName: manager.LastName,
|
||||
Email: manager.Email,
|
||||
PhoneNumber: manager.PhoneNumber,
|
||||
Role: manager.Role,
|
||||
EmailVerified: manager.EmailVerified,
|
||||
PhoneVerified: manager.PhoneVerified,
|
||||
CreatedAt: manager.CreatedAt,
|
||||
UpdatedAt: manager.UpdatedAt,
|
||||
SuspendedAt: manager.SuspendedAt,
|
||||
Suspended: manager.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
}
|
||||
}
|
||||
|
||||
return response.WritePaginatedJSON(c, fiber.StatusOK, "Managers retrieved successfully", result, nil, filter.Page, int(total))
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package handlers
|
|||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
|
|
@ -77,10 +76,10 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
// Checking to make sure the event hasn't already started
|
||||
currentTime := time.Now()
|
||||
if event.StartTime.Before(currentTime) {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
|
||||
}
|
||||
// currentTime := time.Now()
|
||||
// if event.StartTime.Before(currentTime) {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
|
||||
// }
|
||||
|
||||
odds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr)
|
||||
|
||||
|
|
@ -184,8 +183,8 @@ func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
|
|||
|
||||
ticket, err := h.ticketSvc.GetTicketByID(c.Context(), id)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get ticket by ID", "ticketID", id, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve ticket")
|
||||
// h.logger.Error("Failed to get ticket by ID", "ticketID", id, "error", err)
|
||||
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve ticket")
|
||||
}
|
||||
|
||||
res := TicketRes{
|
||||
|
|
|
|||
|
|
@ -9,21 +9,22 @@ import (
|
|||
)
|
||||
|
||||
type TransactionRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
BranchID int64 `json:"branch_id" example:"1"`
|
||||
CashierID int64 `json:"cashier_id" example:"1"`
|
||||
BetID int64 `json:"bet_id" example:"1"`
|
||||
Type int64 `json:"type" example:"1"`
|
||||
PaymentOption domain.PaymentOption `json:"payment_option" example:"1"`
|
||||
FullName string `json:"full_name" example:"John Smith"`
|
||||
PhoneNumber string `json:"phone_number" example:"0911111111"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
BranchID int64 `json:"branch_id" example:"1"`
|
||||
CashierID int64 `json:"cashier_id" example:"1"`
|
||||
BetID int64 `json:"bet_id" example:"1"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes" example:"1"`
|
||||
Type int64 `json:"type" example:"1"`
|
||||
PaymentOption domain.PaymentOption `json:"payment_option" example:"1"`
|
||||
FullName string `json:"full_name" example:"John Smith"`
|
||||
PhoneNumber string `json:"phone_number" example:"0911111111"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
}
|
||||
|
||||
type CreateTransactionReq struct {
|
||||
|
|
@ -115,20 +116,22 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
// TODO: Validate the bet id and add the number of outcomes
|
||||
transaction, err := h.transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{
|
||||
BranchID: branchID,
|
||||
CashierID: userID,
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
BetID: req.BetID,
|
||||
Type: domain.TransactionType(req.Type),
|
||||
PaymentOption: domain.PaymentOption(req.PaymentOption),
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BankCode: req.BankCode,
|
||||
BeneficiaryName: req.BeneficiaryName,
|
||||
AccountName: req.AccountName,
|
||||
AccountNumber: req.AccountNumber,
|
||||
ReferenceNumber: req.ReferenceNumber,
|
||||
BranchID: branchID,
|
||||
CashierID: userID,
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
BetID: req.BetID,
|
||||
NumberOfOutcomes: 1,
|
||||
Type: domain.TransactionType(req.Type),
|
||||
PaymentOption: domain.PaymentOption(req.PaymentOption),
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BankCode: req.BankCode,
|
||||
BeneficiaryName: req.BeneficiaryName,
|
||||
AccountName: req.AccountName,
|
||||
AccountNumber: req.AccountNumber,
|
||||
ReferenceNumber: req.ReferenceNumber,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -232,6 +235,10 @@ func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Transaction retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
type UpdateTransactionVerifiedReq struct {
|
||||
Verified bool `json:"verified" validate:"required" example:"true"`
|
||||
}
|
||||
|
||||
// UpdateTransactionVerified godoc
|
||||
// @Summary Updates the verified field of a transaction
|
||||
// @Description Updates the verified status of a transaction
|
||||
|
|
@ -245,9 +252,6 @@ func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /transaction/{id} [patch]
|
||||
func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
||||
type UpdateTransactionVerifiedReq struct {
|
||||
Verified bool `json:"verified" validate:"required" example:"true"`
|
||||
}
|
||||
|
||||
transactionID := c.Params("id")
|
||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||
|
|
|
|||
|
|
@ -2,14 +2,25 @@ package handlers
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"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"
|
||||
)
|
||||
|
||||
type CheckPhoneEmailExistReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required" example:"1234567890"`
|
||||
}
|
||||
type CheckPhoneEmailExistRes struct {
|
||||
EmailExist bool `json:"email_exist"`
|
||||
PhoneNumberExist bool `json:"phone_number_exist"`
|
||||
}
|
||||
|
||||
// CheckPhoneEmailExist godoc
|
||||
// @Summary Check if phone number or email exist
|
||||
// @Description Check if phone number or email exist
|
||||
|
|
@ -22,14 +33,6 @@ import (
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/checkPhoneEmailExist [post]
|
||||
func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
||||
type CheckPhoneEmailExistReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required" example:"1234567890"`
|
||||
}
|
||||
type CheckPhoneEmailExistRes struct {
|
||||
EmailExist bool `json:"email_exist"`
|
||||
PhoneNumberExist bool `json:"phone_number_exist"`
|
||||
}
|
||||
|
||||
var req CheckPhoneEmailExistReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -54,6 +57,11 @@ func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Check successful", res, nil)
|
||||
}
|
||||
|
||||
type RegisterCodeReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
}
|
||||
|
||||
// SendRegisterCode godoc
|
||||
// @Summary Send register code
|
||||
// @Description Send register code
|
||||
|
|
@ -66,10 +74,6 @@ func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/sendRegisterCode [post]
|
||||
func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
||||
type RegisterCodeReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
}
|
||||
|
||||
var req RegisterCodeReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -101,6 +105,16 @@ func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||
}
|
||||
|
||||
type RegisterUserReq 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"`
|
||||
Otp string `json:"otp" example:"123456"`
|
||||
ReferalCode string `json:"referal_code" example:"ABC123"`
|
||||
}
|
||||
|
||||
// RegisterUser godoc
|
||||
// @Summary Register user
|
||||
// @Description Register user
|
||||
|
|
@ -113,15 +127,6 @@ func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/register [post]
|
||||
func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
||||
type RegisterUserReq 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"`
|
||||
Otp string `json:"otp" example:"123456"`
|
||||
ReferalCode string `json:"referal_code" example:"ABC123"`
|
||||
}
|
||||
|
||||
var req RegisterUserReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -192,6 +197,11 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Registration successful", nil, nil)
|
||||
}
|
||||
|
||||
type ResetCodeReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
}
|
||||
|
||||
// SendResetCode godoc
|
||||
// @Summary Send reset code
|
||||
// @Description Send reset code
|
||||
|
|
@ -204,10 +214,6 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/sendResetCode [post]
|
||||
func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
||||
type ResetCodeReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
}
|
||||
|
||||
var req ResetCodeReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -239,6 +245,13 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
||||
}
|
||||
|
||||
type ResetPasswordReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
Password string `json:"password" validate:"required,min=8" example:"newpassword123"`
|
||||
Otp string `json:"otp" validate:"required" example:"123456"`
|
||||
}
|
||||
|
||||
// ResetPassword godoc
|
||||
// @Summary Reset password
|
||||
// @Description Reset password
|
||||
|
|
@ -251,12 +264,6 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/resetPassword [post]
|
||||
func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
||||
type ResetPasswordReq struct {
|
||||
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
Password string `json:"password" validate:"required,min=8" example:"newpassword123"`
|
||||
Otp string `json:"otp" validate:"required" example:"123456"`
|
||||
}
|
||||
|
||||
var req ResetPasswordReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -301,6 +308,7 @@ type UserProfileRes struct {
|
|||
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"`
|
||||
}
|
||||
|
|
@ -330,6 +338,15 @@ func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user profile")
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", userID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
res := UserProfileRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
|
|
@ -343,6 +360,7 @@ func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
|||
UpdatedAt: user.UpdatedAt,
|
||||
SuspendedAt: user.SuspendedAt,
|
||||
Suspended: user.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "User profile retrieved successfully", res, nil)
|
||||
}
|
||||
|
|
@ -374,6 +392,7 @@ type SearchUserByNameOrPhoneReq struct {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/search [post]
|
||||
func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
||||
// TODO: Add filtering by role based on which user is calling this
|
||||
var req SearchUserByNameOrPhoneReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
||||
|
|
@ -395,6 +414,15 @@ func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
|||
}
|
||||
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
|
||||
for _, user := range users {
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
res = append(res, UserProfileRes{
|
||||
ID: user.ID,
|
||||
FirstName: user.FirstName,
|
||||
|
|
@ -408,8 +436,80 @@ func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
|||
UpdatedAt: user.UpdatedAt,
|
||||
SuspendedAt: user.SuspendedAt,
|
||||
Suspended: user.Suspended,
|
||||
LastLogin: *lastLogin,
|
||||
})
|
||||
}
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Search Successful", res, nil)
|
||||
|
||||
}
|
||||
|
||||
// GetUserByID godoc
|
||||
// @Summary Get user by id
|
||||
// @Description Get a single user by id
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /user/single/{id} [get]
|
||||
func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
||||
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
||||
// filter := user.Filter{
|
||||
// Role: string(domain.RoleUser),
|
||||
// BranchId: user.ValidBranchId{
|
||||
// Value: branchId,
|
||||
// Valid: true,
|
||||
// },
|
||||
// Page: c.QueryInt("page", 1),
|
||||
// PageSize: c.QueryInt("page_size", 10),
|
||||
// }
|
||||
// valErrs, ok := validator.Validate(c, filter)
|
||||
// if !ok {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
// }
|
||||
|
||||
userIDstr := c.Params("id")
|
||||
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("UpdateCashier failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
||||
}
|
||||
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("GetAllCashiers failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
||||
}
|
||||
|
||||
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
if err != authentication.ErrRefreshTokenNotFound {
|
||||
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
||||
}
|
||||
|
||||
lastLogin = &user.CreatedAt
|
||||
}
|
||||
|
||||
res := UserProfileRes{
|
||||
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,
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Cashiers retrieved successfully", res, nil)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,16 @@ import (
|
|||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type launchVirtualGameReq struct {
|
||||
GameID string `json:"game_id" validate:"required" example:"crash_001"`
|
||||
Currency string `json:"currency" validate:"required,len=3" example:"USD"`
|
||||
Mode string `json:"mode" validate:"required,oneof=REAL DEMO" example:"REAL"`
|
||||
}
|
||||
|
||||
type launchVirtualGameRes struct {
|
||||
LaunchURL string `json:"launch_url"`
|
||||
}
|
||||
|
||||
// LaunchVirtualGame godoc
|
||||
// @Summary Launch a PopOK virtual game
|
||||
// @Description Generates a URL to launch a PopOK game
|
||||
|
|
@ -20,15 +30,6 @@ import (
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /virtual-game/launch [post]
|
||||
func (h *Handler) LaunchVirtualGame(c *fiber.Ctx) error {
|
||||
type launchVirtualGameReq struct {
|
||||
GameID string `json:"game_id" validate:"required" example:"crash_001"`
|
||||
Currency string `json:"currency" validate:"required,len=3" example:"USD"`
|
||||
Mode string `json:"mode" validate:"required,oneof=REAL DEMO" example:"REAL"`
|
||||
}
|
||||
|
||||
type launchVirtualGameRes struct {
|
||||
LaunchURL string `json:"launch_url"`
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
if !ok || userID == 0 {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
|||
|
||||
}
|
||||
|
||||
type UpdateWalletActiveReq struct {
|
||||
IsActive bool `json:"is_active" validate:"required" example:"true"`
|
||||
}
|
||||
|
||||
// UpdateWalletActive godoc
|
||||
// @Summary Activate and Deactivate Wallet
|
||||
// @Description Can activate and deactivate wallet
|
||||
|
|
@ -188,9 +192,6 @@ func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /wallet/{id} [patch]
|
||||
func (h *Handler) UpdateWalletActive(c *fiber.Ctx) error {
|
||||
type UpdateWalletActiveReq struct {
|
||||
IsActive bool `json:"is_active" validate:"required" example:"true"`
|
||||
}
|
||||
|
||||
walletID := c.Params("id")
|
||||
id, err := strconv.ParseInt(walletID, 10, 64)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ var (
|
|||
|
||||
type UserClaim struct {
|
||||
jwt.RegisteredClaims
|
||||
UserId int64
|
||||
Role domain.Role
|
||||
BranchId int64
|
||||
UserId int64
|
||||
Role domain.Role
|
||||
CompanyID domain.ValidInt64
|
||||
}
|
||||
|
||||
type PopOKClaim struct {
|
||||
|
|
@ -37,7 +37,7 @@ type JwtConfig struct {
|
|||
JwtAccessExpiry int
|
||||
}
|
||||
|
||||
func CreateJwt(userId int64, Role domain.Role, BranchId int64, key string, expiry int) (string, error) {
|
||||
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",
|
||||
|
|
@ -46,9 +46,9 @@ func CreateJwt(userId int64, Role domain.Role, BranchId int64, key string, expir
|
|||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiry) * time.Second)),
|
||||
},
|
||||
UserId: userId,
|
||||
Role: Role,
|
||||
BranchId: BranchId,
|
||||
UserId: userId,
|
||||
Role: Role,
|
||||
CompanyID: CompanyID,
|
||||
})
|
||||
jwtToken, err := token.SignedString([]byte(key))
|
||||
return jwtToken, err
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
|
|||
}
|
||||
c.Locals("user_id", claim.UserId)
|
||||
c.Locals("role", claim.Role)
|
||||
c.Locals("branch_id", claim.BranchId)
|
||||
c.Locals("company_id", claim.CompanyID)
|
||||
c.Locals("refresh_token", refreshToken)
|
||||
|
||||
return c.Next()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
_ "github.com/SamuelTariku/FortuneBet-Backend/docs"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/handlers"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
fiberSwagger "github.com/swaggo/fiber-swagger"
|
||||
)
|
||||
|
|
@ -33,7 +34,7 @@ func (a *App) initAppRoutes() {
|
|||
|
||||
// Auth Routes
|
||||
a.fiber.Post("/auth/login", h.LoginCustomer)
|
||||
a.fiber.Post("/auth/refresh", a.authMiddleware, h.RefreshToken)
|
||||
a.fiber.Post("/auth/refresh", h.RefreshToken)
|
||||
a.fiber.Post("/auth/logout", a.authMiddleware, h.LogOutCustomer)
|
||||
a.fiber.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(int64)
|
||||
|
|
@ -68,6 +69,7 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Post("/user/sendRegisterCode", h.SendRegisterCode)
|
||||
a.fiber.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)
|
||||
a.fiber.Get("/user/profile", a.authMiddleware, h.UserProfile)
|
||||
a.fiber.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
|
||||
|
||||
a.fiber.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
|
||||
a.fiber.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
|
||||
|
|
@ -81,15 +83,15 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
|
||||
a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)
|
||||
a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
|
||||
//
|
||||
|
||||
a.fiber.Get("/admin", a.authMiddleware, h.GetAllAdmins)
|
||||
a.fiber.Post("/admin", a.authMiddleware, h.CreateAdmin)
|
||||
|
||||
a.fiber.Get("/managers", a.authMiddleware, h.GetAllManagers)
|
||||
a.fiber.Post("/managers", a.authMiddleware, h.CreateManager)
|
||||
a.fiber.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
|
||||
a.fiber.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
|
||||
|
||||
a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||
|
||||
a.fiber.Get("/prematch/odds/:event_id", h.GetPrematchOdds)
|
||||
a.fiber.Get("/prematch/odds", h.GetALLPrematchOdds)
|
||||
a.fiber.Get("/prematch/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
|
||||
|
|
@ -125,6 +127,8 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
|
||||
a.fiber.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
|
||||
a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
||||
a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||
a.fiber.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
||||
|
||||
// Ticket Routes
|
||||
a.fiber.Post("/ticket", h.CreateTicket)
|
||||
|
|
@ -132,12 +136,12 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/ticket/:id", h.GetTicketByID)
|
||||
|
||||
// Bet Routes
|
||||
a.fiber.Post("/bet", h.CreateBet)
|
||||
a.fiber.Get("/bet", h.GetAllBet)
|
||||
a.fiber.Get("/bet/:id", h.GetBetByID)
|
||||
a.fiber.Post("/bet", a.authMiddleware, h.CreateBet)
|
||||
a.fiber.Get("/bet", a.authMiddleware, h.GetAllBet)
|
||||
a.fiber.Get("/bet/:id", a.authMiddleware, h.GetBetByID)
|
||||
a.fiber.Get("/bet/cashout/:id", a.authMiddleware, h.GetBetByCashoutID)
|
||||
a.fiber.Patch("/bet/:id", h.UpdateCashOut)
|
||||
a.fiber.Delete("/bet/:id", h.DeleteBet)
|
||||
a.fiber.Patch("/bet/:id", a.authMiddleware, h.UpdateCashOut)
|
||||
a.fiber.Delete("/bet/:id", a.authMiddleware, h.DeleteBet)
|
||||
|
||||
// Wallet
|
||||
a.fiber.Get("/wallet", h.GetAllWallets)
|
||||
|
|
@ -152,10 +156,10 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||
|
||||
// Transactions /transactions
|
||||
a.fiber.Post("/transaction", h.CreateTransaction)
|
||||
a.fiber.Get("/transaction", h.GetAllTransactions)
|
||||
a.fiber.Get("/transaction/:id", h.GetTransactionByID)
|
||||
a.fiber.Patch("/transaction/:id", h.UpdateTransactionVerified)
|
||||
a.fiber.Post("/transaction", a.authMiddleware, h.CreateTransaction)
|
||||
a.fiber.Get("/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
a.fiber.Get("/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
||||
a.fiber.Patch("/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||
|
||||
// Notification Routes
|
||||
a.fiber.Get("/notifications/ws/connect/:recipientID", h.ConnectSocket)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user