favourtie game and virtual games + providers orchestration fixes
This commit is contained in:
parent
1c7e076be5
commit
299825e797
|
|
@ -71,6 +71,15 @@ CREATE TABLE IF NOT EXISTS virtual_games (
|
|||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_virtual_games_provider_game ON virtual_games (provider_id, game_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS virtual_game_favourites (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
game_id BIGINT NOT NULL REFERENCES virtual_games(id) ON DELETE CASCADE,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
provider_id VARCHAR(100) NOT NULL REFERENCES virtual_game_providers(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (game_id, user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS virtual_game_reports (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
game_id VARCHAR(150) NOT NULL REFERENCES virtual_games(game_id) ON DELETE CASCADE,
|
||||
|
|
|
|||
|
|
@ -200,17 +200,28 @@ WHERE vgt.transaction_type = 'BET'
|
|||
AND vgt.created_at BETWEEN $1 AND $2
|
||||
GROUP BY c.name,
|
||||
vg.name;
|
||||
|
||||
-- name: AddFavoriteGame :exec
|
||||
INSERT INTO favorite_games (user_id, game_id, created_at)
|
||||
VALUES ($1, $2, NOW()) ON CONFLICT (user_id, game_id) DO NOTHING;
|
||||
INSERT INTO virtual_game_favourites (user_id, game_id, provider_id, created_at)
|
||||
VALUES ($1, $2, $3, NOW())
|
||||
ON CONFLICT (game_id, user_id) DO NOTHING;
|
||||
|
||||
-- name: RemoveFavoriteGame :exec
|
||||
DELETE FROM favorite_games
|
||||
WHERE user_id = $1
|
||||
AND game_id = $2;
|
||||
-- name: ListFavoriteGames :many
|
||||
SELECT game_id
|
||||
FROM favorite_games
|
||||
WHERE user_id = $1;
|
||||
DELETE FROM virtual_game_favourites
|
||||
WHERE user_id = $1 AND game_id = $2 AND provider_id = $3;
|
||||
|
||||
-- name: GetUserFavoriteGamesPaginated :many
|
||||
SELECT
|
||||
vg.*
|
||||
FROM virtual_games vg
|
||||
JOIN virtual_game_favourites vf
|
||||
ON vf.game_id = vg.id
|
||||
WHERE
|
||||
vf.user_id = $1
|
||||
AND ($2::varchar IS NULL OR vf.provider_id = $2)
|
||||
ORDER BY vf.created_at DESC
|
||||
LIMIT $3 OFFSET $4;
|
||||
|
||||
-- name: CreateVirtualGame :one
|
||||
INSERT INTO virtual_games (
|
||||
game_id,
|
||||
|
|
|
|||
42
docs/docs.go
42
docs/docs.go
|
|
@ -8108,16 +8108,42 @@ const docTemplate = `{
|
|||
"VirtualGames - Favourites"
|
||||
],
|
||||
"summary": "Get user's favorite games",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Filter by provider ID",
|
||||
"name": "providerID",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Number of results to return",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Results offset",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/domain.GameRecommendation"
|
||||
"$ref": "#/definitions/domain.UnifiedGame"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
|
|
@ -8140,7 +8166,7 @@ const docTemplate = `{
|
|||
"summary": "Add game to favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Game ID to add",
|
||||
"description": "Game ID and Provider ID to add",
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
|
|
@ -8188,13 +8214,20 @@ const docTemplate = `{
|
|||
"name": "gameID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID of the game",
|
||||
"name": "providerID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "removed",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -12740,6 +12773,9 @@ const docTemplate = `{
|
|||
"properties": {
|
||||
"game_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"provider_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8100,16 +8100,42 @@
|
|||
"VirtualGames - Favourites"
|
||||
],
|
||||
"summary": "Get user's favorite games",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Filter by provider ID",
|
||||
"name": "providerID",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Number of results to return",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Results offset",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/domain.GameRecommendation"
|
||||
"$ref": "#/definitions/domain.UnifiedGame"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
|
|
@ -8132,7 +8158,7 @@
|
|||
"summary": "Add game to favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Game ID to add",
|
||||
"description": "Game ID and Provider ID to add",
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
|
|
@ -8180,13 +8206,20 @@
|
|||
"name": "gameID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Provider ID of the game",
|
||||
"name": "providerID",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "removed",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -12732,6 +12765,9 @@
|
|||
"properties": {
|
||||
"game_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"provider_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1430,6 +1430,8 @@ definitions:
|
|||
properties:
|
||||
game_id:
|
||||
type: integer
|
||||
provider_id:
|
||||
type: string
|
||||
type: object
|
||||
domain.FreeSpinRequest:
|
||||
properties:
|
||||
|
|
@ -9783,6 +9785,19 @@ paths:
|
|||
/api/v1/virtual-game/favorites:
|
||||
get:
|
||||
description: Lists the games that the user marked as favorite
|
||||
parameters:
|
||||
- description: Filter by provider ID
|
||||
in: query
|
||||
name: providerID
|
||||
type: string
|
||||
- description: Number of results to return
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: Results offset
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
@ -9790,8 +9805,12 @@ paths:
|
|||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/domain.GameRecommendation'
|
||||
$ref: '#/definitions/domain.UnifiedGame'
|
||||
type: array
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
|
|
@ -9804,7 +9823,7 @@ paths:
|
|||
- application/json
|
||||
description: Adds a game to the user's favorite games list
|
||||
parameters:
|
||||
- description: Game ID to add
|
||||
- description: Game ID and Provider ID to add
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
|
|
@ -9837,13 +9856,18 @@ paths:
|
|||
name: gameID
|
||||
required: true
|
||||
type: integer
|
||||
- description: Provider ID of the game
|
||||
in: query
|
||||
name: providerID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: removed
|
||||
schema:
|
||||
type: string
|
||||
$ref: '#/definitions/domain.Response'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
|
|
|
|||
|
|
@ -1157,9 +1157,16 @@ type VirtualGame struct {
|
|||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type VirtualGameFavourite struct {
|
||||
ID int64 `json:"id"`
|
||||
GameID int64 `json:"game_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ProviderID string `json:"provider_id"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type VirtualGameHistory struct {
|
||||
ID int64 `json:"id"`
|
||||
SessionID pgtype.Text `json:"session_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
Provider pgtype.Text `json:"provider"`
|
||||
|
|
|
|||
|
|
@ -12,17 +12,19 @@ import (
|
|||
)
|
||||
|
||||
const AddFavoriteGame = `-- name: AddFavoriteGame :exec
|
||||
INSERT INTO favorite_games (user_id, game_id, created_at)
|
||||
VALUES ($1, $2, NOW()) ON CONFLICT (user_id, game_id) DO NOTHING
|
||||
INSERT INTO virtual_game_favourites (user_id, game_id, provider_id, created_at)
|
||||
VALUES ($1, $2, $3, NOW())
|
||||
ON CONFLICT (game_id, user_id) DO NOTHING
|
||||
`
|
||||
|
||||
type AddFavoriteGameParams struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
GameID int64 `json:"game_id"`
|
||||
ProviderID string `json:"provider_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddFavoriteGame(ctx context.Context, arg AddFavoriteGameParams) error {
|
||||
_, err := q.db.Exec(ctx, AddFavoriteGame, arg.UserID, arg.GameID)
|
||||
_, err := q.db.Exec(ctx, AddFavoriteGame, arg.UserID, arg.GameID, arg.ProviderID)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +139,7 @@ func (q *Queries) CreateVirtualGame(ctx context.Context, arg CreateVirtualGamePa
|
|||
|
||||
const CreateVirtualGameHistory = `-- name: CreateVirtualGameHistory :one
|
||||
INSERT INTO virtual_game_histories (
|
||||
session_id,
|
||||
-- session_id,
|
||||
user_id,
|
||||
company_id,
|
||||
provider,
|
||||
|
|
@ -161,11 +163,11 @@ VALUES (
|
|||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12
|
||||
$11
|
||||
-- $12
|
||||
)
|
||||
RETURNING id,
|
||||
session_id,
|
||||
-- session_id,
|
||||
user_id,
|
||||
company_id,
|
||||
provider,
|
||||
|
|
@ -182,7 +184,6 @@ RETURNING id,
|
|||
`
|
||||
|
||||
type CreateVirtualGameHistoryParams struct {
|
||||
SessionID pgtype.Text `json:"session_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
Provider pgtype.Text `json:"provider"`
|
||||
|
|
@ -198,7 +199,6 @@ type CreateVirtualGameHistoryParams struct {
|
|||
|
||||
func (q *Queries) CreateVirtualGameHistory(ctx context.Context, arg CreateVirtualGameHistoryParams) (VirtualGameHistory, error) {
|
||||
row := q.db.QueryRow(ctx, CreateVirtualGameHistory,
|
||||
arg.SessionID,
|
||||
arg.UserID,
|
||||
arg.CompanyID,
|
||||
arg.Provider,
|
||||
|
|
@ -214,7 +214,6 @@ func (q *Queries) CreateVirtualGameHistory(ctx context.Context, arg CreateVirtua
|
|||
var i VirtualGameHistory
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.SessionID,
|
||||
&i.UserID,
|
||||
&i.CompanyID,
|
||||
&i.Provider,
|
||||
|
|
@ -662,6 +661,67 @@ func (q *Queries) GetAllVirtualGames(ctx context.Context, arg GetAllVirtualGames
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetUserFavoriteGamesPaginated = `-- name: GetUserFavoriteGamesPaginated :many
|
||||
SELECT
|
||||
vg.id, vg.game_id, vg.provider_id, vg.name, vg.category, vg.device_type, vg.volatility, vg.rtp, vg.has_demo, vg.has_free_bets, vg.bets, vg.thumbnail, vg.status, vg.created_at, vg.updated_at
|
||||
FROM virtual_games vg
|
||||
JOIN virtual_game_favourites vf
|
||||
ON vf.game_id = vg.id
|
||||
WHERE
|
||||
vf.user_id = $1
|
||||
AND ($2::varchar IS NULL OR vf.provider_id = $2)
|
||||
ORDER BY vf.created_at DESC
|
||||
LIMIT $3 OFFSET $4
|
||||
`
|
||||
|
||||
type GetUserFavoriteGamesPaginatedParams struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Column2 string `json:"column_2"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetUserFavoriteGamesPaginated(ctx context.Context, arg GetUserFavoriteGamesPaginatedParams) ([]VirtualGame, error) {
|
||||
rows, err := q.db.Query(ctx, GetUserFavoriteGamesPaginated,
|
||||
arg.UserID,
|
||||
arg.Column2,
|
||||
arg.Limit,
|
||||
arg.Offset,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []VirtualGame
|
||||
for rows.Next() {
|
||||
var i VirtualGame
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.GameID,
|
||||
&i.ProviderID,
|
||||
&i.Name,
|
||||
&i.Category,
|
||||
&i.DeviceType,
|
||||
&i.Volatility,
|
||||
&i.Rtp,
|
||||
&i.HasDemo,
|
||||
&i.HasFreeBets,
|
||||
&i.Bets,
|
||||
&i.Thumbnail,
|
||||
&i.Status,
|
||||
&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 GetVirtualGameProviderByID = `-- name: GetVirtualGameProviderByID :one
|
||||
SELECT id,
|
||||
provider_id,
|
||||
|
|
@ -874,32 +934,6 @@ func (q *Queries) GetVirtualGameTransactionByExternalID(ctx context.Context, ext
|
|||
return i, err
|
||||
}
|
||||
|
||||
const ListFavoriteGames = `-- name: ListFavoriteGames :many
|
||||
SELECT game_id
|
||||
FROM favorite_games
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error) {
|
||||
rows, err := q.db.Query(ctx, ListFavoriteGames, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []int64
|
||||
for rows.Next() {
|
||||
var game_id int64
|
||||
if err := rows.Scan(&game_id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, game_id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const ListVirtualGameProviderReportsByGamesPlayedAsc = `-- name: ListVirtualGameProviderReportsByGamesPlayedAsc :many
|
||||
SELECT id, provider_id, report_date, total_games_played, total_bets, total_payouts, total_profit, total_players, report_type, created_at, updated_at
|
||||
FROM virtual_game_provider_reports
|
||||
|
|
@ -1025,18 +1059,18 @@ func (q *Queries) ListVirtualGameProviders(ctx context.Context, arg ListVirtualG
|
|||
}
|
||||
|
||||
const RemoveFavoriteGame = `-- name: RemoveFavoriteGame :exec
|
||||
DELETE FROM favorite_games
|
||||
WHERE user_id = $1
|
||||
AND game_id = $2
|
||||
DELETE FROM virtual_game_favourites
|
||||
WHERE user_id = $1 AND game_id = $2 AND provider_id = $3
|
||||
`
|
||||
|
||||
type RemoveFavoriteGameParams struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
GameID int64 `json:"game_id"`
|
||||
ProviderID string `json:"provider_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) RemoveFavoriteGame(ctx context.Context, arg RemoveFavoriteGameParams) error {
|
||||
_, err := q.db.Exec(ctx, RemoveFavoriteGame, arg.UserID, arg.GameID)
|
||||
_, err := q.db.Exec(ctx, RemoveFavoriteGame, arg.UserID, arg.GameID, arg.ProviderID)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ type Response struct {
|
|||
MetaData interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
type CallbackErrorResponse struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
// type CallbackErrorResponse struct {
|
||||
// ErrorData interface
|
||||
// Error string `json:"error,omitempty"`
|
||||
// }
|
||||
|
||||
func CalculateWinnings(amount Currency, totalOdds float32) Currency {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
package domain
|
||||
|
||||
type VeliCallbackErrorResponse struct {
|
||||
ErrorStatus int `json:"errorStatus"`
|
||||
ErrorData struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
} `json:"errorData"`
|
||||
}
|
||||
|
||||
type ProviderRequest struct {
|
||||
BrandID string `json:"brandId"`
|
||||
ExtraData bool `json:"extraData"`
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ type FavoriteGame struct {
|
|||
|
||||
type FavoriteGameRequest struct {
|
||||
GameID int64 `json:"game_id"`
|
||||
ProviderID string `json:"provider_id"`
|
||||
}
|
||||
|
||||
type FavoriteGameResponse struct {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,14 @@ type VirtualGameRepository interface {
|
|||
GetVirtualGameTransactionByExternalID(ctx context.Context, externalID string) (*domain.VirtualGameTransaction, error)
|
||||
UpdateVirtualGameTransactionStatus(ctx context.Context, id int64, status string) error
|
||||
// WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error
|
||||
AddFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error)
|
||||
|
||||
AddFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error
|
||||
RemoveFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error
|
||||
ListFavoriteGames(
|
||||
ctx context.Context,
|
||||
userID int64,
|
||||
providerID *string,
|
||||
limit, offset int32,
|
||||
) ([]dbgen.VirtualGame, error)
|
||||
// GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
GetUserGameHistory(ctx context.Context, userID int64) ([]domain.VirtualGameHistory, error)
|
||||
CreateVirtualGameHistory(ctx context.Context, his *domain.VirtualGameHistory) error
|
||||
|
|
@ -138,24 +142,46 @@ func (r *VirtualGameRepo) UpdateVirtualGameProviderEnabled(ctx context.Context,
|
|||
return r.store.queries.UpdateVirtualGameProviderEnabled(ctx, params)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) AddFavoriteGame(ctx context.Context, userID, gameID int64) error {
|
||||
func (r *VirtualGameRepo) AddFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error {
|
||||
params := dbgen.AddFavoriteGameParams{
|
||||
UserID: userID,
|
||||
GameID: gameID,
|
||||
ProviderID: providerID,
|
||||
}
|
||||
|
||||
return r.store.queries.AddFavoriteGame(ctx, params)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error {
|
||||
func (r *VirtualGameRepo) RemoveFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error {
|
||||
params := dbgen.RemoveFavoriteGameParams{
|
||||
UserID: userID,
|
||||
GameID: gameID,
|
||||
ProviderID: providerID,
|
||||
}
|
||||
|
||||
return r.store.queries.RemoveFavoriteGame(ctx, params)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error) {
|
||||
return r.store.queries.ListFavoriteGames(ctx, userID)
|
||||
func (r *VirtualGameRepo) ListFavoriteGames(
|
||||
ctx context.Context,
|
||||
userID int64,
|
||||
providerID *string,
|
||||
limit, offset int32,
|
||||
) ([]dbgen.VirtualGame, error) {
|
||||
|
||||
params := dbgen.GetUserFavoriteGamesPaginatedParams{
|
||||
UserID: userID,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}
|
||||
|
||||
if providerID != nil {
|
||||
params.Column2 = *providerID
|
||||
} else {
|
||||
params.Column2 = ""
|
||||
}
|
||||
|
||||
return r.store.queries.GetUserFavoriteGamesPaginated(ctx, params)
|
||||
}
|
||||
|
||||
func (r *VirtualGameRepo) CountVirtualGameProviders(ctx context.Context) (int64, error) {
|
||||
|
|
|
|||
71
internal/services/virtualGame/orchestration/favourites.go
Normal file
71
internal/services/virtualGame/orchestration/favourites.go
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package orchestration
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
)
|
||||
|
||||
func (s *Service) AddFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error {
|
||||
return s.repo.AddFavoriteGame(ctx, userID, gameID, providerID)
|
||||
}
|
||||
|
||||
func (s *Service) RemoveFavoriteGame(ctx context.Context, userID, gameID int64, providerID string) error {
|
||||
return s.repo.RemoveFavoriteGame(ctx, userID, gameID, providerID)
|
||||
}
|
||||
|
||||
func (s *Service) ListFavoriteGames(
|
||||
ctx context.Context,
|
||||
userID int64,
|
||||
providerID *string,
|
||||
limit, offset int32,
|
||||
) ([]domain.UnifiedGame, error) {
|
||||
|
||||
// Fetch favorite games directly from repository
|
||||
games, err := s.repo.ListFavoriteGames(ctx, userID, providerID, limit, offset)
|
||||
if err != nil {
|
||||
// s.logger.Error("Failed to list favorite games", "userID", userID, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If no favorites, return empty list
|
||||
if len(games) == 0 {
|
||||
return []domain.UnifiedGame{}, nil
|
||||
}
|
||||
|
||||
favorites := make([]domain.UnifiedGame, 0, len(games))
|
||||
|
||||
for _, g := range games {
|
||||
var rtpPtr *float64
|
||||
if g.Rtp.Valid {
|
||||
if f, err := g.Rtp.Float64Value(); err == nil {
|
||||
rtpPtr = new(float64)
|
||||
*rtpPtr = f.Float64
|
||||
}
|
||||
}
|
||||
|
||||
bets := make([]float64, len(g.Bets))
|
||||
for i, b := range g.Bets {
|
||||
bets[i] = float64(b.Exp)
|
||||
}
|
||||
|
||||
favorites = append(favorites, domain.UnifiedGame{
|
||||
GameID: g.GameID, // assuming g.GameID is string
|
||||
ProviderID: g.ProviderID, // provider id
|
||||
Provider: g.ProviderID, // you can map a full name if needed
|
||||
Name: g.Name,
|
||||
Category: g.Category.String, // nullable
|
||||
DeviceType: g.DeviceType.String, // nullable
|
||||
Volatility: g.Volatility.String, // nullable
|
||||
RTP: rtpPtr,
|
||||
HasDemo: g.HasDemo.Bool,
|
||||
HasFreeBets: g.HasFreeBets.Bool,
|
||||
Bets: bets,
|
||||
Thumbnail: g.Thumbnail.String,
|
||||
Status: int(g.Status.Int32),
|
||||
// DemoURL: g..String,
|
||||
})
|
||||
}
|
||||
|
||||
return favorites, nil
|
||||
}
|
||||
1
internal/services/virtualGame/orchestration/report.go
Normal file
1
internal/services/virtualGame/orchestration/report.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package orchestration
|
||||
|
|
@ -297,7 +297,7 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
|||
unified := domain.UnifiedGame{
|
||||
GameID: fmt.Sprintf("%d", g.ID),
|
||||
ProviderID: "popok",
|
||||
Provider: "PopOK",
|
||||
Provider: "Popok Gaming",
|
||||
Name: g.GameName,
|
||||
Category: "Crash",
|
||||
Bets: g.Bets,
|
||||
|
|
@ -416,6 +416,15 @@ func (s *Service) SetProviderEnabled(ctx context.Context, providerID string, ena
|
|||
return domainProvider, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (s *Service) CreateVirtualGameProviderReport(ctx context.Context, report domain.CreateVirtualGameProviderReport) (domain.VirtualGameProviderReport, error) {
|
||||
// Example: logger := s.mongoLogger.With(zap.String("service", "CreateVirtualGameProviderReport"), zap.Any("Report", report))
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ type VirtualGameService interface {
|
|||
// GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
ListGames(ctx context.Context, currency string) ([]domain.PopOKGame, error)
|
||||
RecommendGames(ctx context.Context, userID int64) ([]domain.GameRecommendation, error)
|
||||
AddFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
ListFavoriteGames(ctx context.Context, userID int64) ([]domain.GameRecommendation, error)
|
||||
// AddFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
// RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error
|
||||
// ListFavoriteGames(ctx context.Context, userID int64) ([]domain.GameRecommendation, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -823,47 +823,5 @@ func toInt64Ptr(s string) *int64 {
|
|||
return &id
|
||||
}
|
||||
|
||||
func (s *service) AddFavoriteGame(ctx context.Context, userID, gameID int64) error {
|
||||
return s.repo.AddFavoriteGame(ctx, userID, gameID)
|
||||
}
|
||||
|
||||
func (s *service) RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error {
|
||||
return s.repo.RemoveFavoriteGame(ctx, userID, gameID)
|
||||
}
|
||||
|
||||
func (s *service) ListFavoriteGames(ctx context.Context, userID int64) ([]domain.GameRecommendation, error) {
|
||||
gameIDs, err := s.repo.ListFavoriteGames(ctx, userID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to list favorite games", "userID", userID, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(gameIDs) == 0 {
|
||||
return []domain.GameRecommendation{}, nil
|
||||
}
|
||||
|
||||
allGames, err := s.ListGames(ctx, "ETB") // You can use dynamic currency if needed
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var favorites []domain.GameRecommendation
|
||||
idMap := make(map[int64]bool)
|
||||
for _, id := range gameIDs {
|
||||
idMap[id] = true
|
||||
}
|
||||
|
||||
for _, g := range allGames {
|
||||
if idMap[int64(g.ID)] {
|
||||
favorites = append(favorites, domain.GameRecommendation{
|
||||
GameID: g.ID,
|
||||
GameName: g.GameName,
|
||||
Thumbnail: g.Thumbnail,
|
||||
Bets: g.Bets,
|
||||
Reason: "Marked as favorite",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return favorites, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ type loginAdminReq struct {
|
|||
}
|
||||
|
||||
// loginAdminRes represents the response body for the LoginAdmin endpoint.
|
||||
type loginAdminRes struct {
|
||||
type LoginAdminRes struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Role string `json:"role"`
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func (h *Handler) CreateDirectDeposit(c *fiber.Ctx) error {
|
|||
// Call service
|
||||
deposit, err := h.directDepositSvc.CreateDirectDeposit(c.Context(), req)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateDirectDeposit error", err.Error())
|
||||
// h.logger.Error("CreateDirectDeposit error", err.Error())
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to create direct deposit",
|
||||
Error: err.Error(),
|
||||
|
|
@ -73,7 +73,7 @@ func (h *Handler) GetDirectDepositsByStatus(c *fiber.Ctx) error {
|
|||
|
||||
deposits, total, err := h.directDepositSvc.GetDirectDepositsByStatus(c.Context(), status, page, pageSize)
|
||||
if err != nil {
|
||||
h.logger.Error("GetDirectDepositsByStatus error", err)
|
||||
// h.logger.Error("GetDirectDepositsByStatus error", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch direct deposits",
|
||||
Error: err.Error(),
|
||||
|
|
@ -125,7 +125,7 @@ func (h *Handler) ApproveDirectDeposit(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.directDepositSvc.ApproveDirectDeposit(c.Context(), depositID, adminID); err != nil {
|
||||
h.logger.Error("ApproveDirectDeposit error", err)
|
||||
// h.logger.Error("ApproveDirectDeposit error", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to approve direct deposit",
|
||||
Error: err.Error(),
|
||||
|
|
@ -178,7 +178,7 @@ func (h *Handler) RejectDirectDeposit(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.directDepositSvc.RejectDirectDeposit(c.Context(), depositID, adminID, reason); err != nil {
|
||||
h.logger.Error("RejectDirectDeposit error", err)
|
||||
// h.logger.Error("RejectDirectDeposit error", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to reject direct deposit",
|
||||
Error: err.Error(),
|
||||
|
|
@ -215,7 +215,7 @@ func (h *Handler) GetDirectDepositByID(c *fiber.Ctx) error {
|
|||
|
||||
deposit, err := h.directDepositSvc.GetDirectDepositByID(c.Context(), depositID)
|
||||
if err != nil {
|
||||
h.logger.Error("GetDirectDepositByID error", err)
|
||||
// h.logger.Error("GetDirectDepositByID error", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch direct deposit",
|
||||
Error: err.Error(),
|
||||
|
|
@ -251,7 +251,7 @@ func (h *Handler) DeleteDirectDeposit(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
if err := h.directDepositSvc.DeleteDirectDeposit(c.Context(), depositID); err != nil {
|
||||
h.logger.Error("DeleteDirectDeposit error", err)
|
||||
// h.logger.Error("DeleteDirectDeposit error", err)
|
||||
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to delete direct deposit",
|
||||
Error: err.Error(),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func ParseLeagueIDFromQuery(c *fiber.Ctx) (domain.ValidInt64, error) {
|
|||
if leagueIDQuery != "" {
|
||||
leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64)
|
||||
if err != nil {
|
||||
return domain.ValidInt64{}, fmt.Errorf("Failed to parse league_id %v: %w", leagueIDQuery, err)
|
||||
return domain.ValidInt64{}, fmt.Errorf("failed to parse league_id %v: %w", leagueIDQuery, err)
|
||||
}
|
||||
return domain.ValidInt64{
|
||||
Value: leagueIDInt,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package handlers
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
|
|
@ -346,19 +345,40 @@ func (h *Handler) HandleBet(c *fiber.Ctx) error {
|
|||
res, err := h.veliVirtualGameSvc.ProcessBet(c.Context(), req)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), veli.ErrDuplicateTransaction.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "Duplicate transaction",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrDuplicateTransaction.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
// ErrorData.Er: veli.ErrDuplicateTransaction.Error(),
|
||||
})
|
||||
} else if strings.Contains(err.Error(), veli.ErrInsufficientBalance.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "Wallet balance is insufficient",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrInsufficientBalance.Error(),
|
||||
})
|
||||
Details: nil,
|
||||
}})
|
||||
} else if strings.Contains(err.Error(), veli.ErrPlayerNotFound.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "User not found",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrPlayerNotFound.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
|
|
@ -472,15 +492,29 @@ func (h *Handler) HandleWin(c *fiber.Ctx) error {
|
|||
|
||||
res, err := h.veliVirtualGameSvc.ProcessWin(c.Context(), req)
|
||||
if err != nil {
|
||||
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
if strings.Contains(err.Error(), veli.ErrDuplicateTransaction.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "Duplicate transaction",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrDuplicateTransaction.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
})
|
||||
} else if errors.Is(err, veli.ErrPlayerNotFound) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
} else if strings.Contains(err.Error(), veli.ErrPlayerNotFound.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "Duplicate transaction",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrPlayerNotFound.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
|
|
@ -550,14 +584,28 @@ func (h *Handler) HandleCancel(c *fiber.Ctx) error {
|
|||
res, err := h.veliVirtualGameSvc.ProcessCancel(c.Context(), req)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), veli.ErrDuplicateTransaction.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "Duplicate transaction",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrDuplicateTransaction.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
})
|
||||
} else if strings.Contains(err.Error(), veli.ErrPlayerNotFound.Error()) {
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.CallbackErrorResponse{
|
||||
return c.Status(fiber.StatusConflict).JSON(domain.VeliCallbackErrorResponse{
|
||||
// Message: "User not found",
|
||||
ErrorStatus: 409,
|
||||
ErrorData: struct {
|
||||
Error string `json:"error"`
|
||||
Details *string `json:"details"`
|
||||
}{
|
||||
Error: veli.ErrPlayerNotFound.Error(),
|
||||
Details: nil,
|
||||
},
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
|
|
@ -696,7 +744,7 @@ func (h *Handler) HandlePromoWin(c *fiber.Ctx) error {
|
|||
// @Tags VirtualGames - Favourites
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body domain.FavoriteGameRequest true "Game ID to add"
|
||||
// @Param body body domain.FavoriteGameRequest true "Game ID and Provider ID to add"
|
||||
// @Success 201 {string} domain.Response "created"
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
|
|
@ -706,23 +754,36 @@ func (h *Handler) AddFavorite(c *fiber.Ctx) error {
|
|||
|
||||
var req domain.FavoriteGameRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Could not add favorite game",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err := h.virtualGameSvc.AddFavoriteGame(c.Context(), userID, req.GameID)
|
||||
// Validate required fields
|
||||
if req.GameID == 0 || req.ProviderID == "" {
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "game_id and provider_id are required")
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Could not remove favorite",
|
||||
Error: "game_id and provider_id are required",
|
||||
})
|
||||
}
|
||||
|
||||
// Call service layer with providerID
|
||||
err := h.orchestrationSvc.AddFavoriteGame(c.Context(), userID, req.GameID, req.ProviderID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Could not add favorite",
|
||||
Error: err.Error(),
|
||||
})
|
||||
// return fiber.NewError(fiber.StatusInternalServerError, "Could not add favorite")
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(domain.Response{
|
||||
Message: "Game added to favorites",
|
||||
StatusCode: fiber.StatusCreated,
|
||||
Success: true,
|
||||
})
|
||||
// return c.SendStatus(fiber.StatusCreated)
|
||||
}
|
||||
|
||||
// RemoveFavoriteGame godoc
|
||||
|
|
@ -731,19 +792,46 @@ func (h *Handler) AddFavorite(c *fiber.Ctx) error {
|
|||
// @Tags VirtualGames - Favourites
|
||||
// @Produce json
|
||||
// @Param gameID path int64 true "Game ID to remove"
|
||||
// @Success 200 {string} domain.Response "removed"
|
||||
// @Param providerID query string true "Provider ID of the game"
|
||||
// @Success 200 {object} domain.Response "removed"
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/favorites/{gameID} [delete]
|
||||
func (h *Handler) RemoveFavorite(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
gameID, _ := strconv.ParseInt(c.Params("gameID"), 10, 64)
|
||||
|
||||
err := h.virtualGameSvc.RemoveFavoriteGame(c.Context(), userID, gameID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not remove favorite")
|
||||
var req domain.FavoriteGameRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Could not remove favorite",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
|
||||
// Parse gameID from path
|
||||
if req.GameID == 0 || req.ProviderID == "" {
|
||||
// return fiber.NewError(fiber.StatusBadRequest, "game_id and provider_id are required")
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Could not remove favorite",
|
||||
Error: "game_id and provider_id are required",
|
||||
})
|
||||
}
|
||||
|
||||
// Call service layer
|
||||
err := h.orchestrationSvc.RemoveFavoriteGame(c.Context(), userID, req.GameID, req.ProviderID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Could not remove favorite",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Game removed from favorites",
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ListFavoriteGames godoc
|
||||
|
|
@ -751,17 +839,45 @@ func (h *Handler) RemoveFavorite(c *fiber.Ctx) error {
|
|||
// @Description Lists the games that the user marked as favorite
|
||||
// @Tags VirtualGames - Favourites
|
||||
// @Produce json
|
||||
// @Success 200 {array} domain.GameRecommendation
|
||||
// @Param providerID query string false "Filter by provider ID"
|
||||
// @Param limit query int false "Number of results to return"
|
||||
// @Param offset query int false "Results offset"
|
||||
// @Success 200 {array} domain.UnifiedGame
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/virtual-game/favorites [get]
|
||||
func (h *Handler) ListFavorites(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
|
||||
games, err := h.virtualGameSvc.ListFavoriteGames(c.Context(), userID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Could not fetch favorites")
|
||||
// Parse optional query params
|
||||
providerIDQuery := c.Query("providerID")
|
||||
var providerID *string
|
||||
if providerIDQuery != "" {
|
||||
providerID = &providerIDQuery
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(games)
|
||||
|
||||
limitQuery := c.QueryInt("limit", 10) // default limit 20
|
||||
offsetQuery := c.QueryInt("offset", 0) // default offset 0
|
||||
|
||||
// Call service method
|
||||
games, err := h.orchestrationSvc.ListFavoriteGames(c.Context(), userID, providerID, int32(limitQuery), int32(offsetQuery))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Could not fetch favorites",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Favorite games retrieved successfully",
|
||||
Data: games,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
MetaData: map[string]interface{}{
|
||||
"offset": offsetQuery,
|
||||
"limit": limitQuery,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func IdentifyBetProvider(body []byte) (string, error) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user