virtual game orchestration
This commit is contained in:
parent
6425196115
commit
858fd6ce24
|
|
@ -153,7 +153,7 @@ func main() {
|
|||
virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger)
|
||||
aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger)
|
||||
veliCLient := veli.NewClient(cfg, walletSvc)
|
||||
veliVirtualGameService := veli.New(veliCLient, walletSvc, wallet.TransferStore(store), cfg)
|
||||
veliVirtualGameService := veli.New(vitualGameRepo, veliCLient, walletSvc, wallet.TransferStore(store), cfg)
|
||||
recommendationSvc := recommendation.NewService(recommendationRepo)
|
||||
chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY)
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ func main() {
|
|||
logger,
|
||||
)
|
||||
|
||||
go httpserver.SetupReportCronJobs(context.Background(), reportSvc, "C:/Users/User/Desktop")
|
||||
go httpserver.SetupReportandVirtualGameCronJobs(context.Background(), reportSvc, veliVirtualGameService, "C:/Users/User/Desktop")
|
||||
go httpserver.ProcessBetCashback(context.TODO(), betSvc)
|
||||
|
||||
bankRepository := repository.NewBankRepository(store)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
DROP TABLE IF EXISTS virtual_game_providers;
|
||||
-- Drop tables that depend on service_type_setting
|
||||
DROP TABLE IF EXISTS service_type_setting;
|
||||
-- Drop product-related tables and types
|
||||
|
|
|
|||
|
|
@ -20,6 +20,17 @@ CREATE TABLE IF NOT EXISTS users (
|
|||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS virtual_game_providers (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
provider_id VARCHAR(100) UNIQUE NOT NULL, -- providerId from Veli Games
|
||||
provider_name VARCHAR(255) NOT NULL, -- providerName
|
||||
logo_dark TEXT, -- logoForDark (URL)
|
||||
logo_light TEXT, -- logoForLight (URL)
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE, -- allow enabling/disabling providers
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wallets (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
balance BIGINT NOT NULL DEFAULT 0,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,36 @@
|
|||
-- name: CreateVirtualGameProvider :one
|
||||
INSERT INTO virtual_game_providers (
|
||||
provider_id, provider_name, logo_dark, logo_light, enabled
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
) RETURNING id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at;
|
||||
|
||||
-- name: DeleteVirtualGameProvider :exec
|
||||
DELETE FROM virtual_game_providers
|
||||
WHERE provider_id = $1;
|
||||
|
||||
-- name: GetVirtualGameProviderByID :one
|
||||
SELECT id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
FROM virtual_game_providers
|
||||
WHERE provider_id = $1;
|
||||
|
||||
-- name: ListVirtualGameProviders :many
|
||||
SELECT id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
FROM virtual_game_providers
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountVirtualGameProviders :one
|
||||
SELECT COUNT(*) AS total
|
||||
FROM virtual_game_providers;
|
||||
|
||||
-- name: UpdateVirtualGameProviderEnabled :one
|
||||
UPDATE virtual_game_providers
|
||||
SET enabled = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE provider_id = $1
|
||||
RETURNING id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at;
|
||||
|
||||
-- name: CreateVirtualGameSession :one
|
||||
INSERT INTO virtual_game_sessions (
|
||||
user_id, game_id, session_token, currency, status, expires_at
|
||||
|
|
|
|||
172
docs/docs.go
172
docs/docs.go
|
|
@ -7011,6 +7011,151 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/orchestrator/providers/status": {
|
||||
"patch": {
|
||||
"description": "Sets the enabled status of a provider",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Enable/Disable a provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Enable or Disable",
|
||||
"name": "enabled",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.VirtualGameProvider"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/providers": {
|
||||
"get": {
|
||||
"description": "Lists all providers with pagination",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "List virtual game providers",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Limit",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Offset",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/providers/{provider_id}": {
|
||||
"get": {
|
||||
"description": "Fetches a provider by provider_id",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Get a virtual game provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.VirtualGameProvider"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Deletes a provider by provider_id",
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Remove a virtual game provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/wallet": {
|
||||
"get": {
|
||||
"description": "Retrieve all wallets",
|
||||
|
|
@ -9950,6 +10095,33 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.VirtualGameProvider": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"logo_dark": {
|
||||
"type": "string"
|
||||
},
|
||||
"logo_light": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider_id": {
|
||||
"description": "ID int64 ` + "`" + `json:\"id\" db:\"id\"` + "`" + `",
|
||||
"type": "string"
|
||||
},
|
||||
"provider_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.WebhookRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -7003,6 +7003,151 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/orchestrator/providers/status": {
|
||||
"patch": {
|
||||
"description": "Sets the enabled status of a provider",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Enable/Disable a provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Enable or Disable",
|
||||
"name": "enabled",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.VirtualGameProvider"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/providers": {
|
||||
"get": {
|
||||
"description": "Lists all providers with pagination",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "List virtual game providers",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Limit",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Offset",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-game/providers/{provider_id}": {
|
||||
"get": {
|
||||
"description": "Fetches a provider by provider_id",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Get a virtual game provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.VirtualGameProvider"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Deletes a provider by provider_id",
|
||||
"tags": [
|
||||
"VirtualGames - Orchestration"
|
||||
],
|
||||
"summary": "Remove a virtual game provider",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID",
|
||||
"name": "provider_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/wallet": {
|
||||
"get": {
|
||||
"description": "Retrieve all wallets",
|
||||
|
|
@ -9942,6 +10087,33 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.VirtualGameProvider": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"logo_dark": {
|
||||
"type": "string"
|
||||
},
|
||||
"logo_light": {
|
||||
"type": "string"
|
||||
},
|
||||
"provider_id": {
|
||||
"description": "ID int64 `json:\"id\" db:\"id\"`",
|
||||
"type": "string"
|
||||
},
|
||||
"provider_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.WebhookRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -1743,6 +1743,24 @@ definitions:
|
|||
- deposit_id
|
||||
- is_verified
|
||||
type: object
|
||||
domain.VirtualGameProvider:
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
logo_dark:
|
||||
type: string
|
||||
logo_light:
|
||||
type: string
|
||||
provider_id:
|
||||
description: ID int64 `json:"id" db:"id"`
|
||||
type: string
|
||||
provider_name:
|
||||
type: string
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
domain.WebhookRequest:
|
||||
properties:
|
||||
nonce:
|
||||
|
|
@ -7072,6 +7090,102 @@ paths:
|
|||
summary: Remove game from favorites
|
||||
tags:
|
||||
- VirtualGames - Favourites
|
||||
/api/v1/virtual-game/orchestrator/providers/status:
|
||||
patch:
|
||||
description: Sets the enabled status of a provider
|
||||
parameters:
|
||||
- description: Provider ID
|
||||
in: path
|
||||
name: provider_id
|
||||
required: true
|
||||
type: string
|
||||
- description: Enable or Disable
|
||||
in: query
|
||||
name: enabled
|
||||
required: true
|
||||
type: boolean
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.VirtualGameProvider'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Enable/Disable a provider
|
||||
tags:
|
||||
- VirtualGames - Orchestration
|
||||
/api/v1/virtual-game/providers:
|
||||
get:
|
||||
description: Lists all providers with pagination
|
||||
parameters:
|
||||
- description: Limit
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: Offset
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: List virtual game providers
|
||||
tags:
|
||||
- VirtualGames - Orchestration
|
||||
/api/v1/virtual-game/providers/{provider_id}:
|
||||
delete:
|
||||
description: Deletes a provider by provider_id
|
||||
parameters:
|
||||
- description: Provider ID
|
||||
in: path
|
||||
name: provider_id
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Remove a virtual game provider
|
||||
tags:
|
||||
- VirtualGames - Orchestration
|
||||
get:
|
||||
description: Fetches a provider by provider_id
|
||||
parameters:
|
||||
- description: Provider ID
|
||||
in: path
|
||||
name: provider_id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.VirtualGameProvider'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Get a virtual game provider
|
||||
tags:
|
||||
- VirtualGames - Orchestration
|
||||
/api/v1/wallet:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
|||
|
|
@ -652,6 +652,17 @@ type VirtualGameHistory struct {
|
|||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
||||
type VirtualGameProvider struct {
|
||||
ID int64 `json:"id"`
|
||||
ProviderID string `json:"provider_id"`
|
||||
ProviderName string `json:"provider_name"`
|
||||
LogoDark pgtype.Text `json:"logo_dark"`
|
||||
LogoLight pgtype.Text `json:"logo_light"`
|
||||
Enabled bool `json:"enabled"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type VirtualGameSession struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
|
|
|
|||
|
|
@ -30,6 +30,18 @@ func (q *Queries) AddFavoriteGame(ctx context.Context, arg AddFavoriteGameParams
|
|||
return err
|
||||
}
|
||||
|
||||
const CountVirtualGameProviders = `-- name: CountVirtualGameProviders :one
|
||||
SELECT COUNT(*) AS total
|
||||
FROM virtual_game_providers
|
||||
`
|
||||
|
||||
func (q *Queries) CountVirtualGameProviders(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, CountVirtualGameProviders)
|
||||
var total int64
|
||||
err := row.Scan(&total)
|
||||
return total, err
|
||||
}
|
||||
|
||||
const CreateVirtualGameHistory = `-- name: CreateVirtualGameHistory :one
|
||||
INSERT INTO virtual_game_histories (
|
||||
session_id,
|
||||
|
|
@ -115,6 +127,44 @@ func (q *Queries) CreateVirtualGameHistory(ctx context.Context, arg CreateVirtua
|
|||
return i, err
|
||||
}
|
||||
|
||||
const CreateVirtualGameProvider = `-- name: CreateVirtualGameProvider :one
|
||||
INSERT INTO virtual_game_providers (
|
||||
provider_id, provider_name, logo_dark, logo_light, enabled
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5
|
||||
) RETURNING id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateVirtualGameProviderParams struct {
|
||||
ProviderID string `json:"provider_id"`
|
||||
ProviderName string `json:"provider_name"`
|
||||
LogoDark pgtype.Text `json:"logo_dark"`
|
||||
LogoLight pgtype.Text `json:"logo_light"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateVirtualGameProvider(ctx context.Context, arg CreateVirtualGameProviderParams) (VirtualGameProvider, error) {
|
||||
row := q.db.QueryRow(ctx, CreateVirtualGameProvider,
|
||||
arg.ProviderID,
|
||||
arg.ProviderName,
|
||||
arg.LogoDark,
|
||||
arg.LogoLight,
|
||||
arg.Enabled,
|
||||
)
|
||||
var i VirtualGameProvider
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ProviderID,
|
||||
&i.ProviderName,
|
||||
&i.LogoDark,
|
||||
&i.LogoLight,
|
||||
&i.Enabled,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const CreateVirtualGameSession = `-- name: CreateVirtualGameSession :one
|
||||
INSERT INTO virtual_game_sessions (
|
||||
user_id, game_id, session_token, currency, status, expires_at
|
||||
|
|
@ -225,6 +275,38 @@ func (q *Queries) CreateVirtualGameTransaction(ctx context.Context, arg CreateVi
|
|||
return i, err
|
||||
}
|
||||
|
||||
const DeleteVirtualGameProvider = `-- name: DeleteVirtualGameProvider :exec
|
||||
DELETE FROM virtual_game_providers
|
||||
WHERE provider_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteVirtualGameProvider(ctx context.Context, providerID string) error {
|
||||
_, err := q.db.Exec(ctx, DeleteVirtualGameProvider, providerID)
|
||||
return err
|
||||
}
|
||||
|
||||
const GetVirtualGameProviderByID = `-- name: GetVirtualGameProviderByID :one
|
||||
SELECT id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
FROM virtual_game_providers
|
||||
WHERE provider_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetVirtualGameProviderByID(ctx context.Context, providerID string) (VirtualGameProvider, error) {
|
||||
row := q.db.QueryRow(ctx, GetVirtualGameProviderByID, providerID)
|
||||
var i VirtualGameProvider
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ProviderID,
|
||||
&i.ProviderName,
|
||||
&i.LogoDark,
|
||||
&i.LogoLight,
|
||||
&i.Enabled,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetVirtualGameSessionByToken = `-- name: GetVirtualGameSessionByToken :one
|
||||
SELECT id, user_id, game_id, session_token, currency, status, created_at, updated_at, expires_at
|
||||
FROM virtual_game_sessions
|
||||
|
|
@ -365,6 +447,47 @@ func (q *Queries) ListFavoriteGames(ctx context.Context, userID int64) ([]int64,
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const ListVirtualGameProviders = `-- name: ListVirtualGameProviders :many
|
||||
SELECT id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
FROM virtual_game_providers
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListVirtualGameProvidersParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListVirtualGameProviders(ctx context.Context, arg ListVirtualGameProvidersParams) ([]VirtualGameProvider, error) {
|
||||
rows, err := q.db.Query(ctx, ListVirtualGameProviders, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []VirtualGameProvider
|
||||
for rows.Next() {
|
||||
var i VirtualGameProvider
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ProviderID,
|
||||
&i.ProviderName,
|
||||
&i.LogoDark,
|
||||
&i.LogoLight,
|
||||
&i.Enabled,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const RemoveFavoriteGame = `-- name: RemoveFavoriteGame :exec
|
||||
DELETE FROM favorite_games
|
||||
WHERE user_id = $1 AND game_id = $2
|
||||
|
|
@ -380,6 +503,35 @@ func (q *Queries) RemoveFavoriteGame(ctx context.Context, arg RemoveFavoriteGame
|
|||
return err
|
||||
}
|
||||
|
||||
const UpdateVirtualGameProviderEnabled = `-- name: UpdateVirtualGameProviderEnabled :one
|
||||
UPDATE virtual_game_providers
|
||||
SET enabled = $2,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE provider_id = $1
|
||||
RETURNING id, provider_id, provider_name, logo_dark, logo_light, enabled, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateVirtualGameProviderEnabledParams struct {
|
||||
ProviderID string `json:"provider_id"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateVirtualGameProviderEnabled(ctx context.Context, arg UpdateVirtualGameProviderEnabledParams) (VirtualGameProvider, error) {
|
||||
row := q.db.QueryRow(ctx, UpdateVirtualGameProviderEnabled, arg.ProviderID, arg.Enabled)
|
||||
var i VirtualGameProvider
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ProviderID,
|
||||
&i.ProviderName,
|
||||
&i.LogoDark,
|
||||
&i.LogoLight,
|
||||
&i.Enabled,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const UpdateVirtualGameSessionStatus = `-- name: UpdateVirtualGameSessionStatus :exec
|
||||
UPDATE virtual_game_sessions
|
||||
SET status = $2, updated_at = CURRENT_TIMESTAMP
|
||||
|
|
|
|||
|
|
@ -107,20 +107,6 @@ type VirtualGameTransaction struct {
|
|||
GameSpecificData GameSpecificData `json:"game_specific_data"`
|
||||
}
|
||||
|
||||
// type VirtualGameTransaction struct {
|
||||
// ID int64 `json:"id"`
|
||||
// SessionID int64 `json:"session_id"`
|
||||
// UserID int64 `json:"user_id"`
|
||||
// WalletID int64 `json:"wallet_id"`
|
||||
// TransactionType string `json:"transaction_type"` // BET, WIN, REFUND, JACKPOT_WIN
|
||||
// Amount int64 `json:"amount"`
|
||||
// Currency string `json:"currency"`
|
||||
// ExternalTransactionID string `json:"external_transaction_id"`
|
||||
// Status string `json:"status"` // PENDING, COMPLETED, FAILED
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// UpdatedAt time.Time `json:"updated_at"`
|
||||
// }
|
||||
|
||||
type CreateVirtualGameSession struct {
|
||||
UserID int64
|
||||
GameID string
|
||||
|
|
@ -294,3 +280,22 @@ type PopokLaunchResponse struct {
|
|||
LauncherURL string `json:"launcherURL"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type VirtualGameProvider struct {
|
||||
// ID int64 `json:"id" db:"id"`
|
||||
ProviderID string `json:"provider_id" db:"provider_id"`
|
||||
ProviderName string `json:"provider_name" db:"provider_name"`
|
||||
LogoDark *string `json:"logo_dark,omitempty" db:"logo_dark"`
|
||||
LogoLight *string `json:"logo_light,omitempty" db:"logo_light"`
|
||||
Enabled bool `json:"enabled" db:"enabled"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||
}
|
||||
|
||||
// VirtualGameProviderPagination is used when returning paginated results
|
||||
type VirtualGameProviderPagination struct {
|
||||
Providers []VirtualGameProvider `json:"providers"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
|
@ -12,6 +12,12 @@ import (
|
|||
)
|
||||
|
||||
type VirtualGameRepository interface {
|
||||
CountVirtualGameProviders(ctx context.Context) (int64, error)
|
||||
CreateVirtualGameProvider(ctx context.Context, arg dbgen.CreateVirtualGameProviderParams) (dbgen.VirtualGameProvider, error)
|
||||
DeleteVirtualGameProvider(ctx context.Context, providerID string) error
|
||||
GetVirtualGameProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error)
|
||||
ListVirtualGameProviders(ctx context.Context, limit, offset int32) ([]dbgen.VirtualGameProvider, error)
|
||||
UpdateVirtualGameProviderEnabled(ctx context.Context, providerID string, enabled bool) (dbgen.VirtualGameProvider, error)
|
||||
CreateVirtualGameSession(ctx context.Context, session *domain.VirtualGameSession) error
|
||||
GetVirtualGameSessionByToken(ctx context.Context, token string) (*domain.VirtualGameSession, error)
|
||||
UpdateVirtualGameSessionStatus(ctx context.Context, id int64, status string) error
|
||||
|
|
@ -37,10 +43,80 @@ type VirtualGameRepo struct {
|
|||
// panic("unimplemented")
|
||||
// }
|
||||
|
||||
// func convertDBVirtualGameProvider(p dbgen.VirtualGameProvider) domain.VirtualGameProvider {
|
||||
// var logoDark *string
|
||||
// if p.LogoDark.Valid {
|
||||
// logoDark = &p.LogoDark.String
|
||||
// }
|
||||
// var logoLight *string
|
||||
// if p.LogoLight.Valid {
|
||||
// logoLight = &p.LogoLight.String
|
||||
// }
|
||||
// return domain.VirtualGameProvider{
|
||||
// // ID: p.ID,
|
||||
// ProviderID: p.ProviderID,
|
||||
// ProviderName: p.ProviderName,
|
||||
// LogoDark: logoDark,
|
||||
// LogoLight: logoLight,
|
||||
// Enabled: p.Enabled,
|
||||
// CreatedAt: p.CreatedAt.Time,
|
||||
// UpdatedAt: &p.UpdatedAt.Time,
|
||||
// }
|
||||
// }
|
||||
|
||||
func ConvertCreateVirtualGameProvider(p domain.VirtualGameProvider) dbgen.CreateVirtualGameProviderParams {
|
||||
return dbgen.CreateVirtualGameProviderParams{
|
||||
ProviderID: p.ProviderID,
|
||||
ProviderName: p.ProviderName,
|
||||
LogoDark: pgtype.Text{String: func() string {
|
||||
if p.LogoDark != nil {
|
||||
return *p.LogoDark
|
||||
}
|
||||
return ""
|
||||
}(), Valid: p.LogoDark != nil},
|
||||
LogoLight: pgtype.Text{String: func() string {
|
||||
if p.LogoLight != nil {
|
||||
return *p.LogoLight
|
||||
}
|
||||
return ""
|
||||
}(), Valid: p.LogoLight != nil},
|
||||
Enabled: p.Enabled,
|
||||
// CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewVirtualGameRepository(store *Store) VirtualGameRepository {
|
||||
return &VirtualGameRepo{store: store}
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) CreateVirtualGameProvider(ctx context.Context, arg dbgen.CreateVirtualGameProviderParams) (dbgen.VirtualGameProvider, error) {
|
||||
return r.store.queries.CreateVirtualGameProvider(ctx, arg)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) DeleteVirtualGameProvider(ctx context.Context, providerID string) error {
|
||||
return r.store.queries.DeleteVirtualGameProvider(ctx, providerID)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) GetVirtualGameProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error) {
|
||||
return r.store.queries.GetVirtualGameProviderByID(ctx, providerID)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) ListVirtualGameProviders(ctx context.Context, limit, offset int32) ([]dbgen.VirtualGameProvider, error) {
|
||||
args := dbgen.ListVirtualGameProvidersParams{
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}
|
||||
return r.store.queries.ListVirtualGameProviders(ctx, args)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) UpdateVirtualGameProviderEnabled(ctx context.Context, providerID string, enabled bool) (dbgen.VirtualGameProvider, error) {
|
||||
params := dbgen.UpdateVirtualGameProviderEnabledParams{
|
||||
ProviderID: providerID,
|
||||
Enabled: enabled,
|
||||
}
|
||||
return r.store.queries.UpdateVirtualGameProviderEnabled(ctx, params)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) AddFavoriteGame(ctx context.Context, userID, gameID int64) error {
|
||||
params := dbgen.AddFavoriteGameParams{
|
||||
UserID: userID,
|
||||
|
|
@ -61,6 +137,10 @@ func (r *VirtualGameRepo) ListFavoriteGames(ctx context.Context, userID int64) (
|
|||
return r.store.queries.ListFavoriteGames(ctx, userID)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) CountVirtualGameProviders(ctx context.Context) (int64, error) {
|
||||
return r.store.queries.CountVirtualGameProviders(ctx)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) CreateVirtualGameSession(ctx context.Context, session *domain.VirtualGameSession) error {
|
||||
params := dbgen.CreateVirtualGameSessionParams{
|
||||
UserID: session.UserID,
|
||||
|
|
|
|||
69
internal/services/virtualGame/game_orchestration.go
Normal file
69
internal/services/virtualGame/game_orchestration.go
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package virtualgameservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
||||
// Remove a provider by provider_id
|
||||
func (s *service) RemoveProvider(ctx context.Context, providerID string) error {
|
||||
return s.repo.DeleteVirtualGameProvider(ctx, providerID)
|
||||
}
|
||||
|
||||
// Fetch provider by provider_id
|
||||
func (s *service) GetProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error) {
|
||||
return s.repo.GetVirtualGameProviderByID(ctx, providerID)
|
||||
}
|
||||
|
||||
// List providers with pagination
|
||||
func (s *service) ListProviders(ctx context.Context, limit, offset int32) ([]domain.VirtualGameProvider, int64, error) {
|
||||
providers, err := s.repo.ListVirtualGameProviders(ctx, limit, offset)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
total, err := s.repo.CountVirtualGameProviders(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Convert []dbgen.VirtualGameProvider to []domain.VirtualGameProvider
|
||||
domainProviders := make([]domain.VirtualGameProvider, len(providers))
|
||||
for i, p := range providers {
|
||||
domainProviders[i] = domain.VirtualGameProvider{
|
||||
ProviderID: p.ProviderID,
|
||||
ProviderName: p.ProviderName,
|
||||
Enabled: p.Enabled,
|
||||
CreatedAt: p.CreatedAt.Time,
|
||||
UpdatedAt: &p.UpdatedAt.Time,
|
||||
// Add other fields as needed
|
||||
}
|
||||
}
|
||||
|
||||
return domainProviders, total, nil
|
||||
}
|
||||
|
||||
// Enable/Disable a provider
|
||||
func (s *service) SetProviderEnabled(ctx context.Context, providerID string, enabled bool) (*domain.VirtualGameProvider, error) {
|
||||
provider, err := s.repo.UpdateVirtualGameProviderEnabled(ctx, providerID, enabled)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update provider enabled status", "provider_id", providerID, "enabled", enabled, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now()
|
||||
provider.UpdatedAt.Time = now
|
||||
|
||||
domainProvider := &domain.VirtualGameProvider{
|
||||
ProviderID: provider.ProviderID,
|
||||
ProviderName: provider.ProviderName,
|
||||
Enabled: provider.Enabled,
|
||||
CreatedAt: provider.CreatedAt.Time,
|
||||
UpdatedAt: &provider.UpdatedAt.Time,
|
||||
// Add other fields as needed
|
||||
}
|
||||
|
||||
return domainProvider, nil
|
||||
}
|
||||
|
|
@ -3,10 +3,17 @@ package virtualgameservice
|
|||
import (
|
||||
"context"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
||||
type VirtualGameService interface {
|
||||
// AddProvider(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error)
|
||||
RemoveProvider(ctx context.Context, providerID string) error
|
||||
GetProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error)
|
||||
ListProviders(ctx context.Context, limit, offset int32) ([]domain.VirtualGameProvider, int64, error)
|
||||
SetProviderEnabled(ctx context.Context, providerID string, enabled bool) (*domain.VirtualGameProvider, error)
|
||||
|
||||
GenerateGameLaunchURL(ctx context.Context, userID int64, gameID, currency, mode string) (string, error)
|
||||
HandleCallback(ctx context.Context, callback *domain.PopOKCallback) error
|
||||
ProcessBet(ctx context.Context, req *domain.PopOKBetRequest) (*domain.PopOKBetResponse, error)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ func New(repo repository.VirtualGameRepository, walletSvc wallet.Service, store
|
|||
walletSvc: walletSvc,
|
||||
store: store,
|
||||
config: cfg,
|
||||
logger: logger}
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) GenerateGameLaunchURL(ctx context.Context, userID int64, gameID, currency, mode string) (string, error) {
|
||||
|
|
|
|||
55
internal/services/virtualGame/veli/game_orchestration.go
Normal file
55
internal/services/virtualGame/veli/game_orchestration.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package veli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func (s *Service) AddProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
||||
// 1. Prepare signature parameters
|
||||
sigParams := map[string]any{
|
||||
"brandId": req.BrandID,
|
||||
}
|
||||
|
||||
// Optional fields
|
||||
if req.Size > 0 {
|
||||
sigParams["size"] = fmt.Sprintf("%d", req.Size)
|
||||
} else {
|
||||
sigParams["size"] = ""
|
||||
}
|
||||
|
||||
if req.Page > 0 {
|
||||
sigParams["page"] = fmt.Sprintf("%d", req.Page)
|
||||
} else {
|
||||
sigParams["page"] = ""
|
||||
}
|
||||
|
||||
// 2. Call external API
|
||||
var res domain.ProviderResponse
|
||||
if err := s.client.post(ctx, "/game-lists/public/providers", req, sigParams, &res); err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch providers: %w", err)
|
||||
}
|
||||
|
||||
// 3. Loop through fetched providers and insert into DB
|
||||
for _, p := range res.Items {
|
||||
createParams := dbgen.CreateVirtualGameProviderParams{
|
||||
ProviderID: p.ProviderID,
|
||||
ProviderName: p.ProviderName,
|
||||
LogoDark: pgtype.Text{String: p.LogoForDark, Valid: true},
|
||||
LogoLight: pgtype.Text{String: p.LogoForLight, Valid: true},
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
_, err := s.repo.CreateVirtualGameProvider(ctx, createParams)
|
||||
if err != nil {
|
||||
// Log error but continue with other providers
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type VeliVirtualGameService interface {
|
||||
AddProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error)
|
||||
GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error)
|
||||
GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error)
|
||||
StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||
)
|
||||
|
||||
|
|
@ -18,15 +19,17 @@ var (
|
|||
ErrDuplicateTransaction = errors.New("DUPLICATE_TRANSACTION")
|
||||
)
|
||||
|
||||
type service struct {
|
||||
type Service struct {
|
||||
repo repository.VirtualGameRepository
|
||||
client *Client
|
||||
walletSvc *wallet.Service
|
||||
transfetStore wallet.TransferStore
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func New(client *Client, walletSvc *wallet.Service, transferStore wallet.TransferStore, cfg *config.Config) VeliVirtualGameService {
|
||||
return &service{
|
||||
func New(repo repository.VirtualGameRepository,client *Client, walletSvc *wallet.Service, transferStore wallet.TransferStore, cfg *config.Config) *Service {
|
||||
return &Service{
|
||||
repo: repo,
|
||||
client: client,
|
||||
walletSvc: walletSvc,
|
||||
transfetStore: transferStore,
|
||||
|
|
@ -34,7 +37,7 @@ func New(client *Client, walletSvc *wallet.Service, transferStore wallet.Transfe
|
|||
}
|
||||
}
|
||||
|
||||
func (s *service) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
||||
func (s *Service) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
||||
// Always mirror request body fields into sigParams
|
||||
sigParams := map[string]any{
|
||||
"brandId": req.BrandID,
|
||||
|
|
@ -58,7 +61,7 @@ func (s *service) GetProviders(ctx context.Context, req domain.ProviderRequest)
|
|||
return &res, err
|
||||
}
|
||||
|
||||
func (s *service) GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error) {
|
||||
func (s *Service) GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error) {
|
||||
sigParams := map[string]any{
|
||||
"brandId": req.BrandID, "providerId": req.ProviderID,
|
||||
}
|
||||
|
|
@ -69,7 +72,7 @@ func (s *service) GetGames(ctx context.Context, req domain.GameListRequest) ([]d
|
|||
return res.Items, err
|
||||
}
|
||||
|
||||
func (s *service) StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error) {
|
||||
func (s *Service) StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error) {
|
||||
sigParams := map[string]any{
|
||||
"sessionId": req.SessionID, "providerId": req.ProviderID,
|
||||
"gameId": req.GameID, "language": req.Language, "playerId": req.PlayerID,
|
||||
|
|
@ -81,7 +84,7 @@ func (s *service) StartGame(ctx context.Context, req domain.GameStartRequest) (*
|
|||
return &res, err
|
||||
}
|
||||
|
||||
func (s *service) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) {
|
||||
func (s *Service) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) {
|
||||
sigParams := map[string]any{
|
||||
"providerId": req.ProviderID, "gameId": req.GameID,
|
||||
"language": req.Language, "deviceType": req.DeviceType,
|
||||
|
|
@ -92,8 +95,8 @@ func (s *service) StartDemoGame(ctx context.Context, req domain.DemoGameRequest)
|
|||
return &res, err
|
||||
}
|
||||
|
||||
func (s *service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*domain.BalanceResponse, error) {
|
||||
// Retrieve player's real balance from wallet service
|
||||
func (s *Service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*domain.BalanceResponse, error) {
|
||||
// Retrieve player's real balance from wallet Service
|
||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid PlayerID: %w", err)
|
||||
|
|
@ -140,7 +143,7 @@ func (s *service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*d
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain.BetResponse, error) {
|
||||
func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain.BetResponse, error) {
|
||||
// --- 1. Validate PlayerID ---
|
||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -257,7 +260,7 @@ func (s *service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain.WinResponse, error) {
|
||||
func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain.WinResponse, error) {
|
||||
// --- 1. Validate PlayerID ---
|
||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -336,7 +339,7 @@ func (s *service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (*domain.CancelResponse, error) {
|
||||
func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (*domain.CancelResponse, error) {
|
||||
// --- 1. Validate PlayerID ---
|
||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -434,12 +437,12 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
|||
}
|
||||
|
||||
// Example helper to fetch original bet
|
||||
// func (s *service) getOriginalBet(ctx context.Context, transactionID string) (*domain.BetRecord, error) {
|
||||
// func (s *Service) getOriginalBet(ctx context.Context, transactionID string) (*domain.BetRecord, error) {
|
||||
// // TODO: implement actual lookup
|
||||
// return &domain.BetRecord{Amount: 50}, nil
|
||||
// }
|
||||
|
||||
func (s *service) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) {
|
||||
func (s *Service) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) {
|
||||
// --- Signature Params (flattened strings for signing) ---
|
||||
sigParams := map[string]any{
|
||||
"fromDate": req.FromDate,
|
||||
|
|
@ -487,7 +490,7 @@ func (s *service) GetGamingActivity(ctx context.Context, req domain.GamingActivi
|
|||
return &res, nil
|
||||
}
|
||||
|
||||
func (s *service) GetHugeWins(ctx context.Context, req domain.HugeWinsRequest) (*domain.HugeWinsResponse, error) {
|
||||
func (s *Service) GetHugeWins(ctx context.Context, req domain.HugeWinsRequest) (*domain.HugeWinsResponse, error) {
|
||||
// --- Signature Params (flattened strings for signing) ---
|
||||
sigParams := map[string]any{
|
||||
"fromDate": req.FromDate,
|
||||
|
|
|
|||
|
|
@ -2,18 +2,21 @@ package httpserver
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"log"
|
||||
|
||||
// "time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
betSvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||
resultsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli"
|
||||
"github.com/robfig/cron/v3"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
|
@ -128,17 +131,22 @@ func StartTicketCrons(ticketService ticket.Service, mongoLogger *zap.Logger) {
|
|||
}
|
||||
|
||||
// SetupReportCronJobs schedules periodic report generation
|
||||
func SetupReportCronJobs(ctx context.Context, reportService *report.Service, outputDir string) {
|
||||
func SetupReportandVirtualGameCronJobs(
|
||||
ctx context.Context,
|
||||
reportService *report.Service,
|
||||
virtualGameService *veli.Service, // inject your virtual game service
|
||||
outputDir string,
|
||||
) {
|
||||
c := cron.New(cron.WithSeconds()) // use WithSeconds for testing
|
||||
|
||||
schedule := []struct {
|
||||
spec string
|
||||
period string
|
||||
}{
|
||||
// {
|
||||
// spec: "*/60 * * * * *", // Every 5 minutes
|
||||
// period: "5min",
|
||||
// },
|
||||
{
|
||||
spec: "60 0 0 * * *", // 1 Minute
|
||||
period: "1 minute",
|
||||
},
|
||||
{
|
||||
spec: "0 0 0 * * *", // Daily at midnight
|
||||
period: "daily",
|
||||
|
|
@ -161,14 +169,10 @@ func SetupReportCronJobs(ctx context.Context, reportService *report.Service, out
|
|||
var from, to time.Time
|
||||
|
||||
switch period {
|
||||
// case "5min":
|
||||
// from = now.Add(-5 * time.Minute)
|
||||
// to = now
|
||||
case "daily":
|
||||
from = time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, now.Location())
|
||||
to = time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, now.Location())
|
||||
case "weekly":
|
||||
// last Sunday -> Saturday
|
||||
weekday := int(now.Weekday())
|
||||
daysSinceSunday := (weekday + 7) % 7
|
||||
from = time.Date(now.Year(), now.Month(), now.Day()-daysSinceSunday-7, 0, 0, 0, 0, now.Location())
|
||||
|
|
@ -182,15 +186,32 @@ func SetupReportCronJobs(ctx context.Context, reportService *report.Service, out
|
|||
return
|
||||
}
|
||||
|
||||
// --- Generate Reports ---
|
||||
log.Printf("Running %s report for period %s -> %s", period, from.Format(time.RFC3339), to.Format(time.RFC3339))
|
||||
|
||||
if err := reportService.GenerateReport(ctx, from, to); err != nil {
|
||||
log.Printf("Error generating %s report: %v", period, err)
|
||||
} else {
|
||||
log.Printf("Successfully generated %s report", period)
|
||||
}
|
||||
|
||||
// --- Fetch and Add Virtual Game Providers (daily only) ---
|
||||
if period == "1 minute" {
|
||||
log.Println("Fetching and adding virtual game providers...")
|
||||
req := domain.ProviderRequest{
|
||||
BrandID: os.Getenv("VELI_BRAND_ID"), // adjust to your actual brand ID
|
||||
ExtraData: true,
|
||||
Size: 1000, // or any default value
|
||||
Page: 1, // start from first page
|
||||
}
|
||||
|
||||
if _, err := virtualGameService.AddProviders(ctx, req); err != nil {
|
||||
log.Printf("Error adding virtual game providers: %v", err)
|
||||
} else {
|
||||
log.Println("Successfully added virtual game providers")
|
||||
}
|
||||
}
|
||||
}); err != nil {
|
||||
log.Fatalf("Failed to schedule %s report cron job: %v", period, err)
|
||||
log.Fatalf("Failed to schedule %s cron job: %v", period, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,87 @@ type launchVirtualGameRes struct {
|
|||
LaunchURL string `json:"launch_url"`
|
||||
}
|
||||
|
||||
// RemoveProviderHandler
|
||||
// @Summary Remove a virtual game provider
|
||||
// @Description Deletes a provider by provider_id
|
||||
// @Tags VirtualGames - Orchestration
|
||||
// @Param provider_id path string true "Provider ID"
|
||||
// @Success 200
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/providers/{provider_id} [delete]
|
||||
func (h *Handler) RemoveProvider(c *fiber.Ctx) error {
|
||||
providerID := c.Params("providerID")
|
||||
if err := h.virtualGameSvc.RemoveProvider(c.Context(), providerID); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not remove provider")
|
||||
}
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
// GetProviderHandler
|
||||
// @Summary Get a virtual game provider
|
||||
// @Description Fetches a provider by provider_id
|
||||
// @Tags VirtualGames - Orchestration
|
||||
// @Param provider_id path string true "Provider ID"
|
||||
// @Produce json
|
||||
// @Success 200 {object} domain.VirtualGameProvider
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/providers/{provider_id} [get]
|
||||
func (h *Handler) GetProviderByID(c *fiber.Ctx) error {
|
||||
providerID := c.Params("providerID")
|
||||
provider, err := h.virtualGameSvc.GetProviderByID(c.Context(), providerID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not fetch provider")
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(provider)
|
||||
}
|
||||
|
||||
// ListProvidersHandler
|
||||
// @Summary List virtual game providers
|
||||
// @Description Lists all providers with pagination
|
||||
// @Tags VirtualGames - Orchestration
|
||||
// @Produce json
|
||||
// @Param limit query int false "Limit"
|
||||
// @Param offset query int false "Offset"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/providers [get]
|
||||
func (h *Handler) ListProviders(c *fiber.Ctx) error {
|
||||
limit, _ := strconv.Atoi(c.Query("limit", "20"))
|
||||
offset, _ := strconv.Atoi(c.Query("offset", "0"))
|
||||
|
||||
providers, total, err := h.virtualGameSvc.ListProviders(c.Context(), int32(limit), int32(offset))
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not list providers")
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"total": total,
|
||||
"providers": providers,
|
||||
})
|
||||
}
|
||||
|
||||
// SetProviderEnabledHandler
|
||||
// @Summary Enable/Disable a provider
|
||||
// @Description Sets the enabled status of a provider
|
||||
// @Tags VirtualGames - Orchestration
|
||||
// @Param provider_id path string true "Provider ID"
|
||||
// @Param enabled query bool true "Enable or Disable"
|
||||
// @Produce json
|
||||
// @Success 200 {object} domain.VirtualGameProvider
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/orchestrator/providers/status [patch]
|
||||
func (h *Handler) SetProviderEnabled(c *fiber.Ctx) error {
|
||||
providerID := c.Params("providerID")
|
||||
enabled, _ := strconv.ParseBool(c.Query("enabled", "true"))
|
||||
|
||||
provider, err := h.virtualGameSvc.SetProviderEnabled(c.Context(), providerID, enabled)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not update provider status")
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(provider)
|
||||
}
|
||||
|
||||
// LaunchVirtualGame godoc
|
||||
// @Summary Launch a PopOK virtual game
|
||||
// @Description Generates a URL to launch a PopOK game
|
||||
|
|
|
|||
|
|
@ -341,6 +341,11 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Delete("/virtual-game/favorites/:gameID", a.authMiddleware, h.RemoveFavorite)
|
||||
groupV1.Get("/virtual-game/favorites", a.authMiddleware, h.ListFavorites)
|
||||
|
||||
groupV1.Delete("/virtual-game/orchestrator/providers/:provideID", a.authMiddleware, h.RemoveProvider)
|
||||
groupV1.Get("/virtual-game/orchestrator/providers/:provideID", a.authMiddleware, h.GetProviderByID)
|
||||
groupV1.Get("/virtual-game/orchestrator/providers", a.authMiddleware, h.ListProviders)
|
||||
groupV1.Patch("/virtual-game/orchestrator/providers/:provideID/status", a.authMiddleware, h.SetProviderEnabled)
|
||||
|
||||
//Issue Reporting Routes
|
||||
groupV1.Post("/issues", a.authMiddleware, h.CreateIssue) //anyone who has logged can report a
|
||||
groupV1.Get("/issues/customer/:customer_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user