more veli-games endpoints
This commit is contained in:
commit
bd0859d3ad
|
|
@ -44,6 +44,7 @@ import (
|
|||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
|
|
@ -98,6 +99,7 @@ func main() {
|
|||
v := customvalidator.NewCustomValidator(validator.New())
|
||||
|
||||
// Initialize services
|
||||
settingSvc := settings.NewService(store)
|
||||
authSvc := authentication.NewService(store, store, cfg.RefreshExpiry)
|
||||
userSvc := user.NewService(store, store, cfg)
|
||||
eventSvc := event.New(cfg.Bet365Token, store)
|
||||
|
|
@ -119,7 +121,7 @@ func main() {
|
|||
branchSvc := branch.NewService(store)
|
||||
companySvc := company.NewService(store)
|
||||
leagueSvc := league.New(store)
|
||||
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, notificationSvc)
|
||||
ticketSvc := ticket.NewService(store, eventSvc, *oddsSvc, domain.MongoDBLogger, *settingSvc, notificationSvc)
|
||||
betSvc := bet.NewService(store, eventSvc, *oddsSvc, *walletSvc, *branchSvc, logger, domain.MongoDBLogger)
|
||||
resultSvc := result.NewService(store, cfg, logger, *betSvc, *oddsSvc, eventSvc, leagueSvc, notificationSvc)
|
||||
referalRepo := repository.NewReferralRepository(store)
|
||||
|
|
@ -232,6 +234,7 @@ func main() {
|
|||
currSvc,
|
||||
cfg.Port,
|
||||
v,
|
||||
settingSvc,
|
||||
authSvc,
|
||||
logger,
|
||||
jwtutil.JwtConfig{
|
||||
|
|
|
|||
|
|
@ -303,7 +303,8 @@ CREATE VIEW branch_details AS
|
|||
SELECT branches.*,
|
||||
CONCAT(users.first_name, ' ', users.last_name) AS manager_name,
|
||||
users.phone_number AS manager_phone_number,
|
||||
wallets.balance
|
||||
wallets.balance,
|
||||
wallets.is_active AS wallet_is_active
|
||||
FROM branches
|
||||
LEFT JOIN users ON branches.branch_manager_id = users.id
|
||||
LEFT JOin wallets ON wallets.id = branches.wallet_id;
|
||||
|
|
@ -324,6 +325,25 @@ SELECT tickets.*,
|
|||
FROM tickets
|
||||
LEFT JOIN ticket_outcomes ON tickets.id = ticket_outcomes.ticket_id
|
||||
GROUP BY tickets.id;
|
||||
CREATE VIEW customer_wallet_details AS
|
||||
SELECT cw.id,
|
||||
cw.customer_id,
|
||||
rw.id AS regular_id,
|
||||
rw.balance AS regular_balance,
|
||||
sw.id AS static_id,
|
||||
sw.balance AS static_balance,
|
||||
rw.is_active as regular_is_active,
|
||||
sw.is_active as static_is_active,
|
||||
rw.updated_at as regular_updated_at,
|
||||
sw.updated_at as static_updated_at,
|
||||
cw.created_at,
|
||||
users.first_name,
|
||||
users.last_name,
|
||||
users.phone_number
|
||||
FROM customer_wallets cw
|
||||
JOIN wallets rw ON cw.regular_wallet_id = rw.id
|
||||
JOIN wallets sw ON cw.static_wallet_id = sw.id
|
||||
JOIN users ON users.id = cw.customer_id;
|
||||
-- Foreign Keys
|
||||
ALTER TABLE users
|
||||
ADD CONSTRAINT unique_email UNIQUE (email),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
-- Settings Initial Data
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('max_number_of_outcomes', '30') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('bet_amount_limit', '100000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('daily_ticket_limit', '50') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
INSERT INTO settings (key, value)
|
||||
VALUES ('total_winnings_limit', '1000000') ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
SET value = EXCLUDED.value;
|
||||
|
|
@ -63,6 +63,19 @@ wHERE (
|
|||
AND (
|
||||
is_shop_bet = sqlc.narg('is_shop_bet')
|
||||
OR sqlc.narg('is_shop_bet') IS NULL
|
||||
)
|
||||
AND (
|
||||
full_name ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR phone_number ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR sqlc.narg('query') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < sqlc.narg('created_after')
|
||||
OR sqlc.narg('created_after') IS NULL
|
||||
);
|
||||
-- name: GetBetByID :one
|
||||
SELECT *
|
||||
|
|
@ -83,7 +96,13 @@ WHERE user_id = $1;
|
|||
-- name: GetBetOutcomeByEventID :many
|
||||
SELECT *
|
||||
FROM bet_outcomes
|
||||
WHERE event_id = $1;
|
||||
WHERE (event_id = $1)
|
||||
AND (
|
||||
status = sqlc.narg('filter_status')
|
||||
OR sqlc.narg('filter_status') IS NULL
|
||||
OR status = sqlc.narg('filter_status_2')
|
||||
OR sqlc.narg('filter_status_2') IS NULL
|
||||
);
|
||||
-- name: GetBetOutcomeByBetID :many
|
||||
SELECT *
|
||||
FROM bet_outcomes
|
||||
|
|
@ -103,6 +122,11 @@ UPDATE bet_outcomes
|
|||
SET status = $1
|
||||
WHERE id = $2
|
||||
RETURNING *;
|
||||
-- name: UpdateBetOutcomeStatusByBetID :one
|
||||
UPDATE bet_outcomes
|
||||
SET status = $1
|
||||
WHERE bet_id = $2
|
||||
RETURNING *;
|
||||
-- name: UpdateBetOutcomeStatusForEvent :many
|
||||
UPDATE bet_outcomes
|
||||
SEt status = $1
|
||||
|
|
@ -119,5 +143,3 @@ WHERE id = $1;
|
|||
-- name: DeleteBetOutcome :exec
|
||||
DELETE FROM bet_outcomes
|
||||
WHERE bet_id = $1;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,23 @@ WHERE (
|
|||
AND (
|
||||
is_active = sqlc.narg('is_active')
|
||||
OR sqlc.narg('is_active') IS NULL
|
||||
)
|
||||
AND (
|
||||
branch_manager_id = sqlc.narg('branch_manager_id')
|
||||
OR sqlc.narg('branch_manager_id') IS NULL
|
||||
)
|
||||
AND (
|
||||
name ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR location ILIKE '%' || sqlc.narg('query') || '%'
|
||||
OR sqlc.narg('query') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > sqlc.narg('created_before')
|
||||
OR sqlc.narg('created_before') IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < sqlc.narg('created_after')
|
||||
OR sqlc.narg('created_after') IS NULL
|
||||
);
|
||||
-- name: GetBranchByID :one
|
||||
SELECT *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
-- name: GetSettings :many
|
||||
SELECT *
|
||||
from settings;
|
||||
FROM settings;
|
||||
-- name: GetSetting :one
|
||||
SELECT *
|
||||
FROM settings
|
||||
WHERE key = $1;
|
||||
-- name: SaveSetting :one
|
||||
INSERT INTO settings (key, value, updated_at)
|
||||
VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (key) DO
|
||||
|
|
|
|||
|
|
@ -26,20 +26,13 @@ WHERE id = $1;
|
|||
SELECT *
|
||||
FROM wallets
|
||||
WHERE user_id = $1;
|
||||
-- name: GetAllCustomerWallet :many
|
||||
SELECT *
|
||||
FROM customer_wallet_details;
|
||||
-- name: GetCustomerWallet :one
|
||||
SELECT cw.id,
|
||||
cw.customer_id,
|
||||
rw.id AS regular_id,
|
||||
rw.balance AS regular_balance,
|
||||
sw.id AS static_id,
|
||||
sw.balance AS static_balance,
|
||||
rw.updated_at as regular_updated_at,
|
||||
sw.updated_at as static_updated_at,
|
||||
cw.created_at
|
||||
FROM customer_wallets cw
|
||||
JOIN wallets rw ON cw.regular_wallet_id = rw.id
|
||||
JOIN wallets sw ON cw.static_wallet_id = sw.id
|
||||
WHERE cw.customer_id = $1;
|
||||
SELECT *
|
||||
FROM customer_wallet_details
|
||||
WHERE customer_id = $1;
|
||||
-- name: GetAllBranchWallets :many
|
||||
SELECT wallets.id,
|
||||
wallets.balance,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,19 @@ wHERE (
|
|||
is_shop_bet = $4
|
||||
OR $4 IS NULL
|
||||
)
|
||||
AND (
|
||||
full_name ILIKE '%' || $5 || '%'
|
||||
OR phone_number ILIKE '%' || $5 || '%'
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $7
|
||||
OR $7 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetAllBetsParams struct {
|
||||
|
|
@ -140,6 +153,9 @@ type GetAllBetsParams struct {
|
|||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
IsShopBet pgtype.Bool `json:"is_shop_bet"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) {
|
||||
|
|
@ -148,6 +164,9 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
|||
arg.CompanyID,
|
||||
arg.UserID,
|
||||
arg.IsShopBet,
|
||||
arg.Query,
|
||||
arg.CreatedBefore,
|
||||
arg.CreatedAfter,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -394,11 +413,23 @@ func (q *Queries) GetBetOutcomeByBetID(ctx context.Context, betID int64) ([]BetO
|
|||
const GetBetOutcomeByEventID = `-- name: GetBetOutcomeByEventID :many
|
||||
SELECT id, bet_id, sport_id, event_id, odd_id, home_team_name, away_team_name, market_id, market_name, odd, odd_name, odd_header, odd_handicap, status, expires
|
||||
FROM bet_outcomes
|
||||
WHERE event_id = $1
|
||||
WHERE (event_id = $1)
|
||||
AND (
|
||||
status = $2
|
||||
OR $2 IS NULL
|
||||
OR status = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
func (q *Queries) GetBetOutcomeByEventID(ctx context.Context, eventID int64) ([]BetOutcome, error) {
|
||||
rows, err := q.db.Query(ctx, GetBetOutcomeByEventID, eventID)
|
||||
type GetBetOutcomeByEventIDParams struct {
|
||||
EventID int64 `json:"event_id"`
|
||||
FilterStatus pgtype.Int4 `json:"filter_status"`
|
||||
FilterStatus2 pgtype.Int4 `json:"filter_status_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBetOutcomeByEventID(ctx context.Context, arg GetBetOutcomeByEventIDParams) ([]BetOutcome, error) {
|
||||
rows, err := q.db.Query(ctx, GetBetOutcomeByEventID, arg.EventID, arg.FilterStatus, arg.FilterStatus2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -468,6 +499,41 @@ func (q *Queries) UpdateBetOutcomeStatus(ctx context.Context, arg UpdateBetOutco
|
|||
return i, err
|
||||
}
|
||||
|
||||
const UpdateBetOutcomeStatusByBetID = `-- name: UpdateBetOutcomeStatusByBetID :one
|
||||
UPDATE bet_outcomes
|
||||
SET status = $1
|
||||
WHERE bet_id = $2
|
||||
RETURNING id, bet_id, sport_id, event_id, odd_id, home_team_name, away_team_name, market_id, market_name, odd, odd_name, odd_header, odd_handicap, status, expires
|
||||
`
|
||||
|
||||
type UpdateBetOutcomeStatusByBetIDParams struct {
|
||||
Status int32 `json:"status"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateBetOutcomeStatusByBetID(ctx context.Context, arg UpdateBetOutcomeStatusByBetIDParams) (BetOutcome, error) {
|
||||
row := q.db.QueryRow(ctx, UpdateBetOutcomeStatusByBetID, arg.Status, arg.BetID)
|
||||
var i BetOutcome
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.BetID,
|
||||
&i.SportID,
|
||||
&i.EventID,
|
||||
&i.OddID,
|
||||
&i.HomeTeamName,
|
||||
&i.AwayTeamName,
|
||||
&i.MarketID,
|
||||
&i.MarketName,
|
||||
&i.Odd,
|
||||
&i.OddName,
|
||||
&i.OddHeader,
|
||||
&i.OddHandicap,
|
||||
&i.Status,
|
||||
&i.Expires,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const UpdateBetOutcomeStatusForEvent = `-- name: UpdateBetOutcomeStatusForEvent :many
|
||||
UPDATE bet_outcomes
|
||||
SEt status = $1
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (q *Queries) DeleteBranchOperation(ctx context.Context, arg DeleteBranchOpe
|
|||
}
|
||||
|
||||
const GetAllBranches = `-- name: GetAllBranches :many
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE (
|
||||
company_id = $1
|
||||
|
|
@ -165,15 +165,43 @@ WHERE (
|
|||
is_active = $2
|
||||
OR $2 IS NULL
|
||||
)
|
||||
AND (
|
||||
branch_manager_id = $3
|
||||
OR $3 IS NULL
|
||||
)
|
||||
AND (
|
||||
name ILIKE '%' || $4 || '%'
|
||||
OR location ILIKE '%' || $4 || '%'
|
||||
OR $4 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at > $5
|
||||
OR $5 IS NULL
|
||||
)
|
||||
AND (
|
||||
created_at < $6
|
||||
OR $6 IS NULL
|
||||
)
|
||||
`
|
||||
|
||||
type GetAllBranchesParams struct {
|
||||
CompanyID pgtype.Int8 `json:"company_id"`
|
||||
IsActive pgtype.Bool `json:"is_active"`
|
||||
BranchManagerID pgtype.Int8 `json:"branch_manager_id"`
|
||||
Query pgtype.Text `json:"query"`
|
||||
CreatedBefore pgtype.Timestamp `json:"created_before"`
|
||||
CreatedAfter pgtype.Timestamp `json:"created_after"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllBranches(ctx context.Context, arg GetAllBranchesParams) ([]BranchDetail, error) {
|
||||
rows, err := q.db.Query(ctx, GetAllBranches, arg.CompanyID, arg.IsActive)
|
||||
rows, err := q.db.Query(ctx, GetAllBranches,
|
||||
arg.CompanyID,
|
||||
arg.IsActive,
|
||||
arg.BranchManagerID,
|
||||
arg.Query,
|
||||
arg.CreatedBefore,
|
||||
arg.CreatedAfter,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -195,6 +223,7 @@ func (q *Queries) GetAllBranches(ctx context.Context, arg GetAllBranchesParams)
|
|||
&i.ManagerName,
|
||||
&i.ManagerPhoneNumber,
|
||||
&i.Balance,
|
||||
&i.WalletIsActive,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -257,7 +286,7 @@ func (q *Queries) GetBranchByCashier(ctx context.Context, userID int64) (Branch,
|
|||
}
|
||||
|
||||
const GetBranchByCompanyID = `-- name: GetBranchByCompanyID :many
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE company_id = $1
|
||||
`
|
||||
|
|
@ -285,6 +314,7 @@ func (q *Queries) GetBranchByCompanyID(ctx context.Context, companyID int64) ([]
|
|||
&i.ManagerName,
|
||||
&i.ManagerPhoneNumber,
|
||||
&i.Balance,
|
||||
&i.WalletIsActive,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -297,7 +327,7 @@ func (q *Queries) GetBranchByCompanyID(ctx context.Context, companyID int64) ([]
|
|||
}
|
||||
|
||||
const GetBranchByID = `-- name: GetBranchByID :one
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE id = $1
|
||||
`
|
||||
|
|
@ -319,12 +349,13 @@ func (q *Queries) GetBranchByID(ctx context.Context, id int64) (BranchDetail, er
|
|||
&i.ManagerName,
|
||||
&i.ManagerPhoneNumber,
|
||||
&i.Balance,
|
||||
&i.WalletIsActive,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetBranchByManagerID = `-- name: GetBranchByManagerID :many
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE branch_manager_id = $1
|
||||
`
|
||||
|
|
@ -352,6 +383,7 @@ func (q *Queries) GetBranchByManagerID(ctx context.Context, branchManagerID int6
|
|||
&i.ManagerName,
|
||||
&i.ManagerPhoneNumber,
|
||||
&i.Balance,
|
||||
&i.WalletIsActive,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -411,7 +443,7 @@ func (q *Queries) GetBranchOperations(ctx context.Context, branchID int64) ([]Ge
|
|||
}
|
||||
|
||||
const SearchBranchByName = `-- name: SearchBranchByName :many
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
|
||||
SELECT id, name, location, is_active, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance, wallet_is_active
|
||||
FROM branch_details
|
||||
WHERE name ILIKE '%' || $1 || '%'
|
||||
`
|
||||
|
|
@ -439,6 +471,7 @@ func (q *Queries) SearchBranchByName(ctx context.Context, dollar_1 pgtype.Text)
|
|||
&i.ManagerName,
|
||||
&i.ManagerPhoneNumber,
|
||||
&i.Balance,
|
||||
&i.WalletIsActive,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ type BranchDetail struct {
|
|||
ManagerName interface{} `json:"manager_name"`
|
||||
ManagerPhoneNumber pgtype.Text `json:"manager_phone_number"`
|
||||
Balance pgtype.Int8 `json:"balance"`
|
||||
WalletIsActive pgtype.Bool `json:"wallet_is_active"`
|
||||
}
|
||||
|
||||
type BranchOperation struct {
|
||||
|
|
@ -199,6 +200,23 @@ type CustomerWallet struct {
|
|||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CustomerWalletDetail struct {
|
||||
ID int64 `json:"id"`
|
||||
CustomerID int64 `json:"customer_id"`
|
||||
RegularID int64 `json:"regular_id"`
|
||||
RegularBalance int64 `json:"regular_balance"`
|
||||
StaticID int64 `json:"static_id"`
|
||||
StaticBalance int64 `json:"static_balance"`
|
||||
RegularIsActive bool `json:"regular_is_active"`
|
||||
StaticIsActive bool `json:"static_is_active"`
|
||||
RegularUpdatedAt pgtype.Timestamp `json:"regular_updated_at"`
|
||||
StaticUpdatedAt pgtype.Timestamp `json:"static_updated_at"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
PhoneNumber pgtype.Text `json:"phone_number"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
ID string `json:"id"`
|
||||
SportID pgtype.Int4 `json:"sport_id"`
|
||||
|
|
|
|||
|
|
@ -9,9 +9,27 @@ import (
|
|||
"context"
|
||||
)
|
||||
|
||||
const GetSetting = `-- name: GetSetting :one
|
||||
SELECT key, value, created_at, updated_at
|
||||
FROM settings
|
||||
WHERE key = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSetting(ctx context.Context, key string) (Setting, error) {
|
||||
row := q.db.QueryRow(ctx, GetSetting, key)
|
||||
var i Setting
|
||||
err := row.Scan(
|
||||
&i.Key,
|
||||
&i.Value,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetSettings = `-- name: GetSettings :many
|
||||
SELECT key, value, created_at, updated_at
|
||||
from settings
|
||||
FROM settings
|
||||
`
|
||||
|
||||
func (q *Queries) GetSettings(ctx context.Context) ([]Setting, error) {
|
||||
|
|
|
|||
|
|
@ -143,6 +143,46 @@ func (q *Queries) GetAllBranchWallets(ctx context.Context) ([]GetAllBranchWallet
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetAllCustomerWallet = `-- name: GetAllCustomerWallet :many
|
||||
SELECT id, customer_id, regular_id, regular_balance, static_id, static_balance, regular_is_active, static_is_active, regular_updated_at, static_updated_at, created_at, first_name, last_name, phone_number
|
||||
FROM customer_wallet_details
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllCustomerWallet(ctx context.Context) ([]CustomerWalletDetail, error) {
|
||||
rows, err := q.db.Query(ctx, GetAllCustomerWallet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CustomerWalletDetail
|
||||
for rows.Next() {
|
||||
var i CustomerWalletDetail
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CustomerID,
|
||||
&i.RegularID,
|
||||
&i.RegularBalance,
|
||||
&i.StaticID,
|
||||
&i.StaticBalance,
|
||||
&i.RegularIsActive,
|
||||
&i.StaticIsActive,
|
||||
&i.RegularUpdatedAt,
|
||||
&i.StaticUpdatedAt,
|
||||
&i.CreatedAt,
|
||||
&i.FirstName,
|
||||
&i.LastName,
|
||||
&i.PhoneNumber,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const GetAllWallets = `-- name: GetAllWallets :many
|
||||
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, currency, bonus_balance, cash_balance
|
||||
FROM wallets
|
||||
|
|
@ -226,36 +266,14 @@ func (q *Queries) GetCompanyByWalletID(ctx context.Context, walletID int64) (Com
|
|||
}
|
||||
|
||||
const GetCustomerWallet = `-- name: GetCustomerWallet :one
|
||||
SELECT cw.id,
|
||||
cw.customer_id,
|
||||
rw.id AS regular_id,
|
||||
rw.balance AS regular_balance,
|
||||
sw.id AS static_id,
|
||||
sw.balance AS static_balance,
|
||||
rw.updated_at as regular_updated_at,
|
||||
sw.updated_at as static_updated_at,
|
||||
cw.created_at
|
||||
FROM customer_wallets cw
|
||||
JOIN wallets rw ON cw.regular_wallet_id = rw.id
|
||||
JOIN wallets sw ON cw.static_wallet_id = sw.id
|
||||
WHERE cw.customer_id = $1
|
||||
SELECT id, customer_id, regular_id, regular_balance, static_id, static_balance, regular_is_active, static_is_active, regular_updated_at, static_updated_at, created_at, first_name, last_name, phone_number
|
||||
FROM customer_wallet_details
|
||||
WHERE customer_id = $1
|
||||
`
|
||||
|
||||
type GetCustomerWalletRow struct {
|
||||
ID int64 `json:"id"`
|
||||
CustomerID int64 `json:"customer_id"`
|
||||
RegularID int64 `json:"regular_id"`
|
||||
RegularBalance int64 `json:"regular_balance"`
|
||||
StaticID int64 `json:"static_id"`
|
||||
StaticBalance int64 `json:"static_balance"`
|
||||
RegularUpdatedAt pgtype.Timestamp `json:"regular_updated_at"`
|
||||
StaticUpdatedAt pgtype.Timestamp `json:"static_updated_at"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCustomerWallet(ctx context.Context, customerID int64) (GetCustomerWalletRow, error) {
|
||||
func (q *Queries) GetCustomerWallet(ctx context.Context, customerID int64) (CustomerWalletDetail, error) {
|
||||
row := q.db.QueryRow(ctx, GetCustomerWallet, customerID)
|
||||
var i GetCustomerWalletRow
|
||||
var i CustomerWalletDetail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CustomerID,
|
||||
|
|
@ -263,9 +281,14 @@ func (q *Queries) GetCustomerWallet(ctx context.Context, customerID int64) (GetC
|
|||
&i.RegularBalance,
|
||||
&i.StaticID,
|
||||
&i.StaticBalance,
|
||||
&i.RegularIsActive,
|
||||
&i.StaticIsActive,
|
||||
&i.RegularUpdatedAt,
|
||||
&i.StaticUpdatedAt,
|
||||
&i.CreatedAt,
|
||||
&i.FirstName,
|
||||
&i.LastName,
|
||||
&i.PhoneNumber,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ type BetFilter struct {
|
|||
CompanyID ValidInt64 // Can Be Nullable
|
||||
UserID ValidInt64 // Can Be Nullable
|
||||
IsShopBet ValidBool
|
||||
Query ValidString
|
||||
CreatedBefore ValidTime
|
||||
CreatedAfter ValidTime
|
||||
}
|
||||
|
||||
type GetBet struct {
|
||||
|
|
|
|||
|
|
@ -7,13 +7,17 @@ type Branch struct {
|
|||
WalletID int64
|
||||
BranchManagerID int64
|
||||
CompanyID int64
|
||||
IsSuspended bool
|
||||
IsActive bool
|
||||
IsSelfOwned bool
|
||||
}
|
||||
|
||||
type BranchFilter struct {
|
||||
CompanyID ValidInt64
|
||||
IsSuspended ValidBool
|
||||
IsActive ValidBool
|
||||
BranchManagerID ValidInt64
|
||||
Query ValidString
|
||||
CreatedBefore ValidTime
|
||||
CreatedAfter ValidTime
|
||||
}
|
||||
|
||||
type BranchDetail struct {
|
||||
|
|
@ -24,10 +28,11 @@ type BranchDetail struct {
|
|||
Balance Currency
|
||||
BranchManagerID int64
|
||||
CompanyID int64
|
||||
IsSuspended bool
|
||||
IsActive bool
|
||||
IsSelfOwned bool
|
||||
ManagerName string
|
||||
ManagerPhoneNumber string
|
||||
WalletIsActive bool
|
||||
}
|
||||
|
||||
type SupportedOperation struct {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ type LeagueFilter struct {
|
|||
Offset ValidInt64
|
||||
}
|
||||
|
||||
|
||||
// These leagues are automatically featured when the league is created
|
||||
var FeaturedLeagues = []int64{
|
||||
// Football
|
||||
|
|
@ -46,6 +45,7 @@ var FeaturedLeagues = []int64{
|
|||
10050346, //UEFA Super Cup
|
||||
10081269, //CONCACAF Champions Cup
|
||||
10070189, //CONCACAF Gold Cup
|
||||
10076185, //UEFA Regions Cup
|
||||
|
||||
10067913, //Europe - World Cup Qualifying
|
||||
10040162, //Asia - World Cup Qualifying
|
||||
|
|
|
|||
|
|
@ -13,3 +13,10 @@ type SettingRes struct {
|
|||
Value string `json:"value"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SettingList struct {
|
||||
MaxNumberOfOutcomes int64 `json:"max_number_of_outcomes"`
|
||||
BetAmountLimit Currency `json:"bet_amount_limit"`
|
||||
DailyTicketPerIP int64 `json:"daily_ticket_limit"`
|
||||
TotalWinningLimit Currency `json:"total_winning_limit"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ type Wallet struct {
|
|||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type WalletFilter struct {
|
||||
IsActive ValidBool
|
||||
Query ValidString
|
||||
CreatedBefore ValidTime
|
||||
CreatedAfter ValidTime
|
||||
}
|
||||
|
||||
type CustomerWallet struct {
|
||||
ID int64
|
||||
RegularID int64
|
||||
|
|
@ -28,9 +35,14 @@ type GetCustomerWallet struct {
|
|||
StaticID int64
|
||||
StaticBalance Currency
|
||||
CustomerID int64
|
||||
RegularIsActive bool
|
||||
StaticIsActive bool
|
||||
RegularUpdatedAt time.Time
|
||||
StaticUpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
FirstName string
|
||||
LastName string
|
||||
PhoneNumber string
|
||||
}
|
||||
|
||||
type BranchWallet struct {
|
||||
|
|
|
|||
|
|
@ -213,6 +213,18 @@ func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]doma
|
|||
Bool: filter.IsShopBet.Value,
|
||||
Valid: filter.IsShopBet.Valid,
|
||||
},
|
||||
Query: pgtype.Text{
|
||||
String: filter.Query.Value,
|
||||
Valid: filter.Query.Valid,
|
||||
},
|
||||
CreatedBefore: pgtype.Timestamp{
|
||||
Time: filter.CreatedBefore.Value,
|
||||
Valid: filter.CreatedBefore.Valid,
|
||||
},
|
||||
CreatedAfter: pgtype.Timestamp{
|
||||
Time: filter.CreatedAfter.Value,
|
||||
Valid: filter.CreatedAfter.Valid,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to get all bets",
|
||||
|
|
@ -312,8 +324,19 @@ func (s *Store) UpdateStatus(ctx context.Context, id int64, status domain.Outcom
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *Store) GetBetOutcomeByEventID(ctx context.Context, eventID int64) ([]domain.BetOutcome, error) {
|
||||
outcomes, err := s.queries.GetBetOutcomeByEventID(ctx, eventID)
|
||||
func (s *Store) GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error) {
|
||||
|
||||
outcomes, err := s.queries.GetBetOutcomeByEventID(ctx, dbgen.GetBetOutcomeByEventIDParams{
|
||||
EventID: eventID,
|
||||
FilterStatus: pgtype.Int4{
|
||||
Int32: int32(domain.OUTCOME_STATUS_PENDING),
|
||||
Valid: is_filtered,
|
||||
},
|
||||
FilterStatus2: pgtype.Int4{
|
||||
Int32: int32(domain.OUTCOME_STATUS_ERROR),
|
||||
Valid: is_filtered,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to get bet outcomes by event ID",
|
||||
zap.Int64("event_id", eventID),
|
||||
|
|
@ -364,6 +387,24 @@ func (s *Store) UpdateBetOutcomeStatus(ctx context.Context, id int64, status dom
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateBetOutcomeStatusByBetID(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error) {
|
||||
update, err := s.queries.UpdateBetOutcomeStatusByBetID(ctx, dbgen.UpdateBetOutcomeStatusByBetIDParams{
|
||||
Status: int32(status),
|
||||
BetID: id,
|
||||
})
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to update bet outcome status",
|
||||
zap.Int64("id", id),
|
||||
zap.Int32("status", int32(status)),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.BetOutcome{}, err
|
||||
}
|
||||
|
||||
res := convertDBBetOutcomes(update)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error) {
|
||||
outcomes, err := s.queries.UpdateBetOutcomeStatusForEvent(ctx, dbgen.UpdateBetOutcomeStatusForEventParams{
|
||||
EventID: eventID,
|
||||
|
|
@ -386,10 +427,6 @@ func (s *Store) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int6
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteBet(ctx context.Context, id int64) error {
|
||||
return s.queries.DeleteBet(ctx, id)
|
||||
}
|
||||
|
||||
// GetBetSummary returns aggregated bet statistics
|
||||
func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
||||
totalStakes domain.Currency,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ func convertDBBranchDetail(dbBranch dbgen.BranchDetail) domain.BranchDetail {
|
|||
ManagerName: dbBranch.ManagerName.(string),
|
||||
ManagerPhoneNumber: dbBranch.ManagerPhoneNumber.String,
|
||||
Balance: domain.Currency(dbBranch.Balance.Int64),
|
||||
IsActive: dbBranch.IsActive,
|
||||
WalletIsActive: dbBranch.WalletIsActive.Bool,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +142,22 @@ func (s *Store) GetAllBranches(ctx context.Context, filter domain.BranchFilter)
|
|||
Int64: filter.CompanyID.Value,
|
||||
Valid: filter.CompanyID.Valid,
|
||||
},
|
||||
BranchManagerID: pgtype.Int8{
|
||||
Int64: filter.BranchManagerID.Value,
|
||||
Valid: filter.BranchManagerID.Valid,
|
||||
},
|
||||
Query: pgtype.Text{
|
||||
String: filter.Query.Value,
|
||||
Valid: filter.Query.Valid,
|
||||
},
|
||||
CreatedBefore: pgtype.Timestamp{
|
||||
Time: filter.CreatedBefore.Value,
|
||||
Valid: filter.CreatedBefore.Valid,
|
||||
},
|
||||
CreatedAfter: pgtype.Timestamp{
|
||||
Time: filter.CreatedAfter.Value,
|
||||
Valid: filter.CreatedAfter.Valid,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ func (s *Store) GetBranchByWalletID(ctx context.Context, walletID int64) (domain
|
|||
ID: dbBranch.ID,
|
||||
Name: dbBranch.Name,
|
||||
Location: dbBranch.Location,
|
||||
IsSuspended: dbBranch.IsActive,
|
||||
IsActive: dbBranch.IsActive,
|
||||
WalletID: dbBranch.WalletID,
|
||||
BranchManagerID: dbBranch.BranchManagerID,
|
||||
CompanyID: dbBranch.CompanyID,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
|
|
@ -44,7 +45,7 @@ func (r *ReferralRepo) UpdateUserReferalCode(ctx context.Context, codedata domai
|
|||
|
||||
func (r *ReferralRepo) CreateReferral(ctx context.Context, referral *domain.Referral) error {
|
||||
rewardAmount := pgtype.Numeric{}
|
||||
if err := rewardAmount.Scan(referral.RewardAmount); err != nil {
|
||||
if err := rewardAmount.Scan(strconv.Itoa(int(referral.RewardAmount))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,74 @@ package repository
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DBSettingList struct {
|
||||
MaxNumberOfOutcomes domain.ValidInt64
|
||||
BetAmountLimit domain.ValidInt64
|
||||
DailyTicketPerIP domain.ValidInt64
|
||||
TotalWinningLimit domain.ValidInt64
|
||||
}
|
||||
|
||||
func GetDBSettingList(settings []dbgen.Setting) (domain.SettingList, error) {
|
||||
var dbSettingList DBSettingList
|
||||
var int64SettingsMap = map[string]*domain.ValidInt64{
|
||||
"max_number_of_outcomes": &dbSettingList.MaxNumberOfOutcomes,
|
||||
"bet_amount_limit": &dbSettingList.BetAmountLimit,
|
||||
"daily_ticket_limit": &dbSettingList.DailyTicketPerIP,
|
||||
"total_winnings_limit": &dbSettingList.TotalWinningLimit,
|
||||
}
|
||||
|
||||
for _, setting := range settings {
|
||||
is_setting_unknown := true
|
||||
for key, dbSetting := range int64SettingsMap {
|
||||
if setting.Key == key {
|
||||
value, err := strconv.ParseInt(setting.Value, 10, 64)
|
||||
if err != nil {
|
||||
return domain.SettingList{}, err
|
||||
}
|
||||
*dbSetting = domain.ValidInt64{
|
||||
Value: value,
|
||||
Valid: true,
|
||||
}
|
||||
is_setting_unknown = false
|
||||
}
|
||||
}
|
||||
|
||||
if is_setting_unknown {
|
||||
domain.MongoDBLogger.Warn("unknown setting found on database", zap.String("setting", setting.Key))
|
||||
}
|
||||
}
|
||||
|
||||
for key, dbSetting := range int64SettingsMap {
|
||||
if !dbSetting.Valid {
|
||||
fmt.Printf("setting value not found on database: %v \n", key)
|
||||
domain.MongoDBLogger.Warn("setting value not found on database", zap.String("setting", key))
|
||||
}
|
||||
}
|
||||
|
||||
return domain.SettingList{
|
||||
MaxNumberOfOutcomes: dbSettingList.MaxNumberOfOutcomes.Value,
|
||||
BetAmountLimit: domain.Currency(dbSettingList.BetAmountLimit.Value),
|
||||
DailyTicketPerIP: dbSettingList.DailyTicketPerIP.Value,
|
||||
TotalWinningLimit: domain.Currency(dbSettingList.TotalWinningLimit.Value),
|
||||
}, nil
|
||||
}
|
||||
func (s *Store) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
||||
settings, err := s.queries.GetSettings(ctx)
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to get all settings", zap.Error(err))
|
||||
}
|
||||
|
||||
return GetDBSettingList(settings)
|
||||
}
|
||||
|
||||
func (s *Store) GetSettings(ctx context.Context) ([]domain.Setting, error) {
|
||||
settings, err := s.queries.GetSettings(ctx)
|
||||
|
||||
|
|
@ -27,6 +89,22 @@ func (s *Store) GetSettings(ctx context.Context) ([]domain.Setting, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetSetting(ctx context.Context, key string) (domain.Setting, error) {
|
||||
dbSetting, err := s.queries.GetSetting(ctx, key)
|
||||
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to get all settings", zap.Error(err))
|
||||
}
|
||||
|
||||
result := domain.Setting{
|
||||
Key: dbSetting.Key,
|
||||
Value: dbSetting.Value,
|
||||
UpdatedAt: dbSetting.UpdatedAt.Time,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) {
|
||||
dbSetting, err := s.queries.SaveSetting(ctx, dbgen.SaveSettingParams{
|
||||
Key: key,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func convertCreateCustomerWallet(customerWallet domain.CreateCustomerWallet) dbg
|
|||
}
|
||||
}
|
||||
|
||||
func convertDBGetCustomerWallet(customerWallet dbgen.GetCustomerWalletRow) domain.GetCustomerWallet {
|
||||
func convertDBGetCustomerWallet(customerWallet dbgen.CustomerWalletDetail) domain.GetCustomerWallet {
|
||||
return domain.GetCustomerWallet{
|
||||
ID: customerWallet.ID,
|
||||
RegularID: customerWallet.RegularID,
|
||||
|
|
@ -55,9 +55,14 @@ func convertDBGetCustomerWallet(customerWallet dbgen.GetCustomerWalletRow) domai
|
|||
StaticID: customerWallet.StaticID,
|
||||
StaticBalance: domain.Currency(customerWallet.StaticBalance),
|
||||
CustomerID: customerWallet.CustomerID,
|
||||
RegularIsActive: customerWallet.RegularIsActive,
|
||||
StaticIsActive: customerWallet.StaticIsActive,
|
||||
RegularUpdatedAt: customerWallet.RegularUpdatedAt.Time,
|
||||
StaticUpdatedAt: customerWallet.StaticUpdatedAt.Time,
|
||||
CreatedAt: customerWallet.CreatedAt.Time,
|
||||
FirstName: customerWallet.FirstName,
|
||||
LastName: customerWallet.LastName,
|
||||
PhoneNumber: customerWallet.PhoneNumber.String,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +120,19 @@ func (s *Store) GetWalletsByUser(ctx context.Context, userID int64) ([]domain.Wa
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetAllCustomerWallets(ctx context.Context) ([]domain.GetCustomerWallet, error) {
|
||||
customerWallets, err := s.queries.GetAllCustomerWallet(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []domain.GetCustomerWallet = make([]domain.GetCustomerWallet, 0, len(customerWallets))
|
||||
for _, wallet := range customerWallets {
|
||||
result = append(result, convertDBGetCustomerWallet(wallet))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetCustomerWallet(ctx context.Context, customerID int64) (domain.GetCustomerWallet, error) {
|
||||
customerWallet, err := s.queries.GetCustomerWallet(ctx, customerID)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ type BetStore interface {
|
|||
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error)
|
||||
GetBetByBranchID(ctx context.Context, BranchID int64) ([]domain.GetBet, error)
|
||||
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
|
||||
GetBetOutcomeByEventID(ctx context.Context, eventID int64) ([]domain.BetOutcome, error)
|
||||
GetBetOutcomeByEventID(ctx context.Context, eventID int64, is_filtered bool) ([]domain.BetOutcome, error)
|
||||
GetBetOutcomeByBetID(ctx context.Context, betID int64) ([]domain.BetOutcome, error)
|
||||
GetBetCount(ctx context.Context, userID int64, outcomesHash string) (int64, error)
|
||||
UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error
|
||||
UpdateStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error
|
||||
UpdateBetOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
||||
UpdateBetOutcomeStatusByBetID(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
||||
UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int64, status domain.OutcomeStatus) ([]domain.BetOutcome, error)
|
||||
DeleteBet(ctx context.Context, id int64) error
|
||||
|
||||
GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
||||
totalStakes domain.Currency,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ var (
|
|||
ErrRawOddInvalid = errors.New("Prematch Raw Odd is Invalid")
|
||||
ErrBranchIDRequired = errors.New("Branch ID required for this role")
|
||||
ErrOutcomeLimit = errors.New("Too many outcomes on a single bet")
|
||||
ErrTotalBalanceNotEnough = errors.New("Total Wallet balance is insufficient to create bet")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
|
@ -326,7 +327,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
newBet.IsShopBet = true
|
||||
|
||||
case domain.RoleCustomer:
|
||||
wallets, err := s.walletSvc.GetWalletsByUser(ctx, userID)
|
||||
wallets, err := s.walletSvc.GetCustomerWallet(ctx, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get customer wallets",
|
||||
zap.Int64("user_id", userID),
|
||||
|
|
@ -334,18 +335,53 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
userWallet := wallets[0]
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, userWallet.ID,
|
||||
if req.Amount < wallets.RegularBalance.Float32() {
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
domain.ToCurrency(req.Amount), domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer",
|
||||
zap.Int64("wallet_id", userWallet.ID),
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
} else {
|
||||
combinedBalance := wallets.RegularBalance + wallets.StaticBalance
|
||||
if req.Amount > combinedBalance.Float32() {
|
||||
return domain.CreateBetRes{}, ErrTotalBalanceNotEnough
|
||||
}
|
||||
// Empty the regular balance
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.RegularID,
|
||||
wallets.RegularBalance, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer regular wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("regular wallet_id", wallets.RegularID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
// Empty remaining from static balance
|
||||
remainingAmount := wallets.RegularBalance - domain.Currency(req.Amount)
|
||||
_, err = s.walletSvc.DeductFromWallet(ctx, wallets.StaticID,
|
||||
remainingAmount, domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("wallet deduction failed for customer static wallet",
|
||||
zap.Int64("customer_id", wallets.CustomerID),
|
||||
zap.Int64("customer_wallet_id", wallets.ID),
|
||||
zap.Int64("static wallet_id", wallets.StaticID),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
newBet.UserID = domain.ValidInt64{Value: userID, Valid: true}
|
||||
newBet.IsShopBet = false
|
||||
|
|
@ -838,8 +874,23 @@ func (s *Service) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID in
|
|||
return outcomes, nil
|
||||
}
|
||||
|
||||
func (s *Service) DeleteBet(ctx context.Context, id int64) error {
|
||||
return s.betStore.DeleteBet(ctx, id)
|
||||
func (s *Service) SetBetToRemoved(ctx context.Context, id int64) error {
|
||||
_, err := s.betStore.UpdateBetOutcomeStatusByBetID(ctx, id, domain.OUTCOME_STATUS_VOID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to update bet outcome to void", zap.Int64("id", id),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.betStore.UpdateStatus(ctx, id, domain.OUTCOME_STATUS_VOID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to update bet to void", zap.Int64("id", id),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
||||
|
|
|
|||
|
|
@ -215,9 +215,8 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, sour
|
|||
for sportIndex, sportID := range sportIDs {
|
||||
var totalPages int = 1
|
||||
var page int = 0
|
||||
var limit int = 1
|
||||
var limit int = 200
|
||||
var count int = 0
|
||||
log.Printf("Sport ID %d", sportID)
|
||||
for page <= totalPages {
|
||||
page = page + 1
|
||||
url := fmt.Sprintf(url, sportID, s.token, page)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/base32"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"time"
|
||||
|
|
@ -53,15 +54,23 @@ func (s *Service) GenerateReferralCode() (string, error) {
|
|||
|
||||
func (s *Service) CreateReferral(ctx context.Context, userID int64) error {
|
||||
s.logger.Info("Creating referral code for user", "userID", userID)
|
||||
// TODO: check in user already has an active referral code
|
||||
code, err := s.GenerateReferralCode()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to generate referral code", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.repo.UpdateUserReferalCode(ctx, domain.UpdateUserReferalCode{
|
||||
UserID: userID,
|
||||
Code: code,
|
||||
// TODO: get the referral settings from db
|
||||
var rewardAmount float64 = 100
|
||||
var expireDuration time.Time = time.Now().Add(24 * time.Hour)
|
||||
|
||||
if err := s.repo.CreateReferral(ctx, &domain.Referral{
|
||||
ReferralCode: code,
|
||||
ReferrerID: fmt.Sprintf("%d", userID),
|
||||
Status: domain.ReferralPending,
|
||||
RewardAmount: rewardAmount,
|
||||
ExpiresAt: expireDuration,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -73,12 +82,12 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
|
|||
s.logger.Info("Processing referral", "referredPhone", referredPhone, "referralCode", referralCode)
|
||||
|
||||
referral, err := s.repo.GetReferralByCode(ctx, referralCode)
|
||||
if err != nil {
|
||||
if err != nil || referral == nil {
|
||||
s.logger.Error("Failed to get referral by code", "referralCode", referralCode, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if referral == nil || referral.Status != domain.ReferralPending || referral.ExpiresAt.Before(time.Now()) {
|
||||
if referral.Status != domain.ReferralPending || referral.ExpiresAt.Before(time.Now()) {
|
||||
s.logger.Warn("Invalid or expired referral", "referralCode", referralCode, "status", referral.Status)
|
||||
return ErrInvalidReferral
|
||||
}
|
||||
|
|
@ -106,27 +115,21 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
|
|||
return err
|
||||
}
|
||||
|
||||
referrerID, err := strconv.ParseInt(referral.ReferrerID, 10, 64)
|
||||
referrerId, err := strconv.Atoi(referral.ReferrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid referrer phone number format", "referrerID", referral.ReferrerID, "error", err)
|
||||
return errors.New("invalid referrer phone number format")
|
||||
}
|
||||
|
||||
wallets, err := s.walletSvc.GetWalletsByUser(ctx, referrerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get wallets for referrer", "referrerID", referrerID, "error", err)
|
||||
s.logger.Error("Failed to convert referrer id", "referrerId", referral.ReferrerID, "error", err)
|
||||
return err
|
||||
}
|
||||
if len(wallets) == 0 {
|
||||
s.logger.Error("Referrer has no wallet", "referrerID", referrerID)
|
||||
return errors.New("referrer has no wallet")
|
||||
|
||||
wallets, err := s.store.GetCustomerWallet(ctx, int64(referrerId))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get referrer wallets", "referrerId", referral.ReferrerID, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
walletID := wallets[0].ID
|
||||
currentBonus := float64(wallets[0].Balance)
|
||||
_, err = s.walletSvc.AddToWallet(ctx, walletID, domain.ToCurrency(float32(currentBonus+referral.RewardAmount)), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
|
||||
_, err = s.walletSvc.AddToWallet(ctx, wallets.StaticID, domain.ToCurrency(float32(referral.RewardAmount)), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to add referral reward to wallet", "walletID", walletID, "referrerID", referrerID, "error", err)
|
||||
s.logger.Error("Failed to add referral reward to static wallet", "walletID", wallets.StaticID, "referrer phone number", referredPhone, "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ var (
|
|||
|
||||
func (s *Service) UpdateResultForOutcomes(ctx context.Context, eventID int64, resultRes json.RawMessage, sportID int64) error {
|
||||
// TODO: Optimize this since there could be many outcomes with the same event_id and market_id that could be updated the same time
|
||||
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID)
|
||||
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID, true)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get pending bet outcomes", "error", err)
|
||||
return fmt.Errorf("failed to get pending bet outcomes for event %d: %w", eventID, err)
|
||||
|
|
@ -108,7 +108,7 @@ func (s *Service) UpdateResultForOutcomes(ctx context.Context, eventID int64, re
|
|||
}
|
||||
|
||||
func (s *Service) RefundAllOutcomes(ctx context.Context, eventID int64) error {
|
||||
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID)
|
||||
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID, false)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get pending bet outcomes", "error", err)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
)
|
||||
|
||||
type SettingStore interface {
|
||||
GetSettingList(ctx context.Context) (domain.SettingList, error)
|
||||
GetSettings(ctx context.Context) ([]domain.Setting, error)
|
||||
GetSetting(ctx context.Context, key string) (domain.Setting, error)
|
||||
SaveSetting(ctx context.Context, key, value string) (domain.Setting, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,17 @@ func NewService(settingStore SettingStore) *Service {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Service) GetSettingList(ctx context.Context) (domain.SettingList, error) {
|
||||
return s.settingStore.GetSettingList(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetSettings(ctx context.Context) ([]domain.Setting, error) {
|
||||
return s.settingStore.GetSettings(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetSetting(ctx context.Context, key string) (domain.Setting, error) {
|
||||
return s.settingStore.GetSetting(ctx, key)
|
||||
}
|
||||
func (s *Service) SaveSetting(ctx context.Context, key, value string) (domain.Setting, error) {
|
||||
return s.settingStore.SaveSetting(ctx, key, value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrGenerateRandomOutcome = errors.New("Failed to generate any random outcome for events")
|
||||
// ErrOutcomesNotCompleted = errors.New("Some bet outcomes are still pending")
|
||||
ErrEventHasNotEnded = errors.New("Event has not ended yet")
|
||||
ErrTicketHasExpired = errors.New("Ticket has expired")
|
||||
ErrNoEventsAvailable = errors.New("Not enough events available with the given filters")
|
||||
ErrEventHasBeenRemoved = errors.New("Event has been removed")
|
||||
ErrTooManyOutcomesForTicket = errors.New("Too many odds/outcomes for a single ticket")
|
||||
|
|
@ -33,6 +34,7 @@ type Service struct {
|
|||
eventSvc event.Service
|
||||
prematchSvc odds.ServiceImpl
|
||||
mongoLogger *zap.Logger
|
||||
settingSvc settings.Service
|
||||
notificationSvc *notificationservice.Service
|
||||
}
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ func NewService(
|
|||
eventSvc event.Service,
|
||||
prematchSvc odds.ServiceImpl,
|
||||
mongoLogger *zap.Logger,
|
||||
settingSvc settings.Service,
|
||||
notificationSvc *notificationservice.Service,
|
||||
) *Service {
|
||||
return &Service{
|
||||
|
|
@ -48,11 +51,12 @@ func NewService(
|
|||
eventSvc: eventSvc,
|
||||
prematchSvc: prematchSvc,
|
||||
mongoLogger: mongoLogger,
|
||||
settingSvc: settingSvc,
|
||||
notificationSvc: notificationSvc,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) GenerateTicketOutcome(ctx context.Context, eventID int64, marketID int64, oddID int64) (domain.CreateTicketOutcome, error) {
|
||||
func (s *Service) GenerateTicketOutcome(ctx context.Context, settings domain.SettingList, eventID int64, marketID int64, oddID int64) (domain.CreateTicketOutcome, error) {
|
||||
eventIDStr := strconv.FormatInt(eventID, 10)
|
||||
marketIDStr := strconv.FormatInt(marketID, 10)
|
||||
oddIDStr := strconv.FormatInt(oddID, 10)
|
||||
|
|
@ -73,7 +77,7 @@ func (s *Service) GenerateTicketOutcome(ctx context.Context, eventID int64, mark
|
|||
zap.Time("event_start_time", event.StartTime),
|
||||
zap.Time("current_time", currentTime),
|
||||
)
|
||||
return domain.CreateTicketOutcome{}, ErrEventHasNotEnded
|
||||
return domain.CreateTicketOutcome{}, ErrTicketHasExpired
|
||||
}
|
||||
|
||||
odds, err := s.prematchSvc.GetRawOddsByMarketID(ctx, marketIDStr, eventIDStr)
|
||||
|
|
@ -155,36 +159,38 @@ func (s *Service) GenerateTicketOutcome(ctx context.Context, eventID int64, mark
|
|||
}
|
||||
|
||||
func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq, clientIP string) (domain.Ticket, int64, error) {
|
||||
settingsList, err := s.settingSvc.GetSettingList(ctx)
|
||||
|
||||
// s.mongoLogger.Info("Creating ticket")
|
||||
// TODO Validate Outcomes Here and make sure they didn't expire
|
||||
// Validation for creating tickets
|
||||
if len(req.Outcomes) > 30 {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "Too many odds/outcomes selected", nil, nil)
|
||||
// Check to see if the number of outcomes is above a set limit
|
||||
if len(req.Outcomes) > int(settingsList.MaxNumberOfOutcomes) {
|
||||
return domain.Ticket{}, 0, ErrTooManyOutcomesForTicket
|
||||
|
||||
}
|
||||
|
||||
if req.Amount > 100000 {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "Cannot create a ticket with an amount above 100,000 birr", nil, nil)
|
||||
// Check to see if the amount is above a set limit
|
||||
if req.Amount > settingsList.BetAmountLimit.Float32() {
|
||||
return domain.Ticket{}, 0, ErrTicketAmountTooHigh
|
||||
}
|
||||
|
||||
count, err := s.CountTicketByIP(ctx, clientIP)
|
||||
|
||||
if err != nil {
|
||||
// return response.WriteJSON(c, fiber.StatusInternalServerError, "Error fetching user info", nil, nil)
|
||||
s.mongoLogger.Error("failed to count number of ticket using ip",
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.Ticket{}, 0, err
|
||||
}
|
||||
|
||||
if count > 50 {
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "Ticket Limit reached", nil, nil)
|
||||
// Check to see how many tickets a single anonymous user has created
|
||||
if count > settingsList.DailyTicketPerIP {
|
||||
|
||||
return domain.Ticket{}, 0, ErrTicketLimitForSingleUser
|
||||
}
|
||||
|
||||
var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes))
|
||||
var totalOdds float32 = 1
|
||||
for _, outcomeReq := range req.Outcomes {
|
||||
newOutcome, err := s.GenerateTicketOutcome(ctx, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID)
|
||||
newOutcome, err := s.GenerateTicketOutcome(ctx, settingsList, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to generate outcome",
|
||||
zap.Int64("event_id", outcomeReq.EventID),
|
||||
|
|
@ -198,9 +204,13 @@ func (s *Service) CreateTicket(ctx context.Context, req domain.CreateTicketReq,
|
|||
outcomes = append(outcomes, newOutcome)
|
||||
}
|
||||
totalWinnings := req.Amount * totalOdds
|
||||
if totalWinnings > 1000000 {
|
||||
s.mongoLogger.Error("Total Winnings over limit", zap.Float32("Total Odds", totalOdds), zap.Float32("amount", req.Amount))
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "Cannot create a ticket with 1,000,000 winnings", nil, nil)
|
||||
|
||||
// Check to see if the total winning amount is over a set limit
|
||||
if totalWinnings > settingsList.TotalWinningLimit.Float32() {
|
||||
s.mongoLogger.Error("Total Winnings over limit",
|
||||
zap.Float32("Total Odds", totalOdds),
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Float32("limit", settingsList.TotalWinningLimit.Float32()))
|
||||
return domain.Ticket{}, 0, ErrTicketWinningTooHigh
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type WalletStore interface {
|
|||
GetWalletByID(ctx context.Context, id int64) (domain.Wallet, error)
|
||||
GetAllWallets(ctx context.Context) ([]domain.Wallet, error)
|
||||
GetWalletsByUser(ctx context.Context, id int64) ([]domain.Wallet, error)
|
||||
GetAllCustomerWallets(ctx context.Context) ([]domain.GetCustomerWallet, error)
|
||||
GetCustomerWallet(ctx context.Context, customerID int64) (domain.GetCustomerWallet, error)
|
||||
GetAllBranchWallets(ctx context.Context) ([]domain.BranchWallet, error)
|
||||
UpdateBalance(ctx context.Context, id int64, balance domain.Currency) error
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ func (s *Service) GetWalletsByUser(ctx context.Context, id int64) ([]domain.Wall
|
|||
return s.walletStore.GetWalletsByUser(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) GetAllCustomerWallet(ctx context.Context) ([]domain.GetCustomerWallet, error) {
|
||||
return s.walletStore.GetAllCustomerWallets(ctx)
|
||||
}
|
||||
func (s *Service) GetCustomerWallet(ctx context.Context, customerID int64) (domain.GetCustomerWallet, error) {
|
||||
return s.walletStore.GetCustomerWallet(ctx, customerID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
|
|
@ -50,6 +51,7 @@ type App struct {
|
|||
NotidicationStore *notificationservice.Service
|
||||
referralSvc referralservice.ReferralStore
|
||||
port int
|
||||
settingSvc *settings.Service
|
||||
authSvc *authentication.Service
|
||||
userSvc *user.Service
|
||||
betSvc *bet.Service
|
||||
|
|
@ -76,6 +78,7 @@ func NewApp(
|
|||
instSvc *institutions.Service,
|
||||
currSvc *currency.Service,
|
||||
port int, validator *customvalidator.CustomValidator,
|
||||
settingSvc *settings.Service,
|
||||
authSvc *authentication.Service,
|
||||
logger *slog.Logger,
|
||||
JwtConfig jwtutil.JwtConfig,
|
||||
|
|
@ -121,6 +124,8 @@ func NewApp(
|
|||
currSvc: currSvc,
|
||||
fiber: app,
|
||||
port: port,
|
||||
|
||||
settingSvc: settingSvc,
|
||||
authSvc: authSvc,
|
||||
validator: validator,
|
||||
logger: logger,
|
||||
|
|
|
|||
|
|
@ -23,22 +23,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
spec string
|
||||
task func()
|
||||
}{
|
||||
// {
|
||||
// spec: "0 0 * * * *", // Every 1 hour
|
||||
// task: func() {
|
||||
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||||
// log.Printf("FetchUpcomingEvents error: %v", err)
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
||||
// task: func() {
|
||||
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||
// log.Printf("FetchNonLiveOdds error: %v", err)
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
{
|
||||
spec: "0 0 * * * *", // Every 1 hour
|
||||
task: func() {
|
||||
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||||
log.Printf("FetchUpcomingEvents error: %v", err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
spec: "0 0 * * * *", // Every 1 hour (since its takes that long to fetch all the events)
|
||||
task: func() {
|
||||
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||
log.Printf("FetchNonLiveOdds error: %v", err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
spec: "0 */5 * * * *", // Every 5 Minutes
|
||||
task: func() {
|
||||
|
|
@ -66,7 +66,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
}
|
||||
|
||||
for _, job := range schedule {
|
||||
job.task()
|
||||
// job.task()
|
||||
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||||
log.Fatalf("Failed to schedule cron job: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,13 +209,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /sport/bet [get]
|
||||
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
||||
role := c.Locals("role").(domain.Role)
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
branchID := c.Locals("branch_id").(domain.ValidInt64)
|
||||
|
||||
var isShopBet domain.ValidBool
|
||||
isShopBetQuery := c.Query("is_shop")
|
||||
|
||||
if isShopBetQuery != "" {
|
||||
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
|
||||
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to parse is_shop_bet",
|
||||
|
|
@ -231,10 +231,47 @@ func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|||
}
|
||||
}
|
||||
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
createdBeforeQuery := c.Query("created_before")
|
||||
var createdBefore domain.ValidTime
|
||||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
createdAfterQuery := c.Query("created_after")
|
||||
var createdAfter domain.ValidTime
|
||||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
|
||||
BranchID: branchID,
|
||||
CompanyID: companyID,
|
||||
IsShopBet: isShopBet,
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to get bets",
|
||||
|
|
@ -432,7 +469,7 @@ func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
||||
}
|
||||
|
||||
err = h.betSvc.DeleteBet(c.Context(), id)
|
||||
err = h.betSvc.SetBetToRemoved(c.Context(), id)
|
||||
if err != nil {
|
||||
h.mongoLoggerSvc.Error("Failed to delete bet by ID",
|
||||
zap.Int64("betID", id),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package handlers
|
|||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
|
|
@ -56,6 +57,7 @@ type BranchRes struct {
|
|||
BranchManagerID int64 `json:"branch_manager_id" example:"1"`
|
||||
CompanyID int64 `json:"company_id" example:"1"`
|
||||
IsSelfOwned bool `json:"is_self_owned" example:"false"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
}
|
||||
|
||||
type BranchDetailRes struct {
|
||||
|
|
@ -69,6 +71,8 @@ type BranchDetailRes struct {
|
|||
ManagerName string `json:"manager_name" example:"John Smith"`
|
||||
ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"`
|
||||
Balance float32 `json:"balance" example:"100.5"`
|
||||
IsActive bool `json:"is_active" example:"false"`
|
||||
WalletIsActive bool `json:"is_wallet_active" example:"false"`
|
||||
}
|
||||
|
||||
func convertBranch(branch domain.Branch) BranchRes {
|
||||
|
|
@ -80,6 +84,7 @@ func convertBranch(branch domain.Branch) BranchRes {
|
|||
BranchManagerID: branch.BranchManagerID,
|
||||
CompanyID: branch.CompanyID,
|
||||
IsSelfOwned: branch.IsSelfOwned,
|
||||
IsActive: branch.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +100,8 @@ func convertBranchDetail(branch domain.BranchDetail) BranchDetailRes {
|
|||
ManagerName: branch.ManagerName,
|
||||
ManagerPhoneNumber: branch.ManagerPhoneNumber,
|
||||
Balance: branch.Balance.Float32(),
|
||||
IsActive: branch.IsActive,
|
||||
WalletIsActive: branch.WalletIsActive,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -391,13 +398,63 @@ func (h *Handler) GetAllBranches(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid is_active param", err, nil)
|
||||
}
|
||||
|
||||
branchManagerQuery := c.Query("branch_manager_id")
|
||||
var branchManagerID domain.ValidInt64
|
||||
if branchManagerQuery != "" {
|
||||
parseManagerID, err := strconv.ParseInt(branchManagerQuery, 10, 64)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse branch_manager_id")
|
||||
}
|
||||
branchManagerID = domain.ValidInt64{
|
||||
Value: parseManagerID,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
searchQuery := c.Query("query")
|
||||
searchString := domain.ValidString{
|
||||
Value: searchQuery,
|
||||
Valid: searchQuery != "",
|
||||
}
|
||||
|
||||
createdBeforeQuery := c.Query("created_before")
|
||||
var createdBefore domain.ValidTime
|
||||
if createdBeforeQuery != "" {
|
||||
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
}
|
||||
createdBefore = domain.ValidTime{
|
||||
Value: createdBeforeParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
createdAfterQuery := c.Query("created_after")
|
||||
var createdAfter domain.ValidTime
|
||||
if createdAfterQuery != "" {
|
||||
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
|
||||
if err != nil {
|
||||
h.logger.Error("invalid start_time format", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
||||
}
|
||||
createdAfter = domain.ValidTime{
|
||||
Value: createdAfterParsed,
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
branches, err := h.branchSvc.GetAllBranches(c.Context(),
|
||||
domain.BranchFilter{
|
||||
CompanyID: companyID,
|
||||
IsSuspended: domain.ValidBool{
|
||||
IsActive: domain.ValidBool{
|
||||
Value: isActive,
|
||||
Valid: isActiveValid,
|
||||
},
|
||||
BranchManagerID: branchManagerID,
|
||||
Query: searchString,
|
||||
CreatedBefore: createdBefore,
|
||||
CreatedAfter: createdAfter,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get branches", "error", err)
|
||||
|
|
|
|||
|
|
@ -184,7 +184,34 @@ func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
|
|||
res := convertGetCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetCompanyForAdmin godoc
|
||||
// @Summary Gets company by id
|
||||
// @Description Gets a single company by id
|
||||
// @Tags company
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} CompanyRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /admin-company [get]
|
||||
func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error {
|
||||
companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
if !companyID.Valid {
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid company ID", nil, nil)
|
||||
}
|
||||
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get company by ID", "companyID", companyID.Value, "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
|
||||
}
|
||||
|
||||
res := convertGetCompany(company)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
|
||||
}
|
||||
|
||||
// GetAllCompanies godoc
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/settings"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
|
|
@ -37,6 +38,7 @@ type Handler struct {
|
|||
instSvc *institutions.Service
|
||||
currSvc *currency.Service
|
||||
logger *slog.Logger
|
||||
settingSvc *settings.Service
|
||||
notificationSvc *notificationservice.Service
|
||||
userSvc *user.Service
|
||||
referralSvc referralservice.ReferralStore
|
||||
|
|
@ -68,6 +70,7 @@ func New(
|
|||
instSvc *institutions.Service,
|
||||
currSvc *currency.Service,
|
||||
logger *slog.Logger,
|
||||
settingSvc *settings.Service,
|
||||
notificationSvc *notificationservice.Service,
|
||||
validator *customvalidator.CustomValidator,
|
||||
reportSvc report.ReportStore,
|
||||
|
|
@ -98,6 +101,7 @@ func New(
|
|||
instSvc: instSvc,
|
||||
currSvc: currSvc,
|
||||
logger: logger,
|
||||
settingSvc: settingSvc,
|
||||
notificationSvc: notificationSvc,
|
||||
reportSvc: reportSvc,
|
||||
chapaSvc: chapaSvc,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package handlers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
|
@ -20,7 +21,7 @@ import (
|
|||
// @Router /api/v1/logs [get]
|
||||
func GetLogsHandler(appCtx context.Context) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
client, err := mongo.Connect(appCtx, options.Client().ApplyURI("mongodb://root:secret@mongo:27017/?authSource=admin"))
|
||||
client, err := mongo.Connect(appCtx, options.Client().ApplyURI(os.Getenv("MONGODB_URL")))
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "MongoDB connection failed: "+err.Error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,6 +179,8 @@ type TopLeaguesRes struct {
|
|||
type TopLeague struct {
|
||||
LeagueID int64 `json:"league_id"`
|
||||
LeagueName string `json:"league_name"`
|
||||
LeagueCC string `json:"league_cc"`
|
||||
LeagueSportID int32 `json:"league_sport_id"`
|
||||
Events []domain.UpcomingEvent `json:"events"`
|
||||
// Total int64 `json:"total"`
|
||||
}
|
||||
|
|
@ -188,7 +190,7 @@ type TopLeague struct {
|
|||
// @Tags prematch
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} domain.UpcomingEvent
|
||||
// @Success 200 {array} TopLeague
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /top-leagues [get]
|
||||
func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
||||
|
|
@ -213,10 +215,11 @@ func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
|
|||
fmt.Printf("Error while fetching events for top league %v \n", league.ID)
|
||||
h.logger.Error("Error while fetching events for top league", "League ID", league.ID)
|
||||
}
|
||||
|
||||
topLeague = append(topLeague, TopLeague{
|
||||
LeagueID: league.ID,
|
||||
LeagueName: league.Name,
|
||||
LeagueCC: league.CountryCode,
|
||||
LeagueSportID: league.SportID,
|
||||
Events: events,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
|
||||
if err != nil {
|
||||
switch err {
|
||||
case ticket.ErrEventHasBeenRemoved, ticket.ErrEventHasNotEnded, ticket.ErrRawOddInvalid:
|
||||
case ticket.ErrEventHasBeenRemoved, ticket.ErrTicketHasExpired,
|
||||
ticket.ErrRawOddInvalid, ticket.ErrTooManyOutcomesForTicket,
|
||||
ticket.ErrTicketAmountTooHigh, ticket.ErrTicketLimitForSingleUser,
|
||||
ticket.ErrTicketWinningTooHigh:
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
|||
type RegisterCodeReq struct {
|
||||
Email string `json:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
Provider domain.OtpProvider `json:"provider" validate:"required" example:"twilio"`
|
||||
}
|
||||
|
||||
// SendRegisterCode godoc
|
||||
|
|
@ -99,7 +98,7 @@ func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
||||
}
|
||||
|
||||
if err := h.userSvc.SendRegisterCode(c.Context(), medium, sentTo, req.Provider); err != nil {
|
||||
if err := h.userSvc.SendRegisterCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||
h.logger.Error("Failed to send register code", "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send register code")
|
||||
}
|
||||
|
|
@ -115,7 +114,6 @@ type RegisterUserReq struct {
|
|||
Password string `json:"password" example:"password123"`
|
||||
Otp string `json:"otp" example:"123456"`
|
||||
ReferalCode string `json:"referal_code" example:"ABC123"`
|
||||
Provider domain.OtpProvider `json:"provider" validate:"required" example:"twilio"`
|
||||
}
|
||||
|
||||
// RegisterUser godoc
|
||||
|
|
@ -176,11 +174,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusInternalServerError, "Unknown Error")
|
||||
}
|
||||
|
||||
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
|
||||
UserID: newUser.ID,
|
||||
IsWithdraw: true,
|
||||
IsBettable: true,
|
||||
})
|
||||
newWallet, err := h.walletSvc.CreateCustomerWallet(c.Context(), newUser.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to create wallet for user", "userID", newUser.ID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet")
|
||||
|
|
@ -195,7 +189,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
|
||||
// TODO: Remove later
|
||||
_, err = h.walletSvc.AddToWallet(
|
||||
c.Context(), newWallet.ID, domain.ToCurrency(100.0), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
|
||||
c.Context(), newWallet.RegularID, domain.ToCurrency(100.0), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update wallet for user", "userID", newUser.ID, "error", err)
|
||||
|
|
@ -208,7 +202,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|||
type ResetCodeReq struct {
|
||||
Email string `json:"email" example:"john.doe@example.com"`
|
||||
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
||||
Provider domain.OtpProvider `json:"provider" validate:"required" example:"twilio"`
|
||||
// Provider domain.OtpProvider `json:"provider" validate:"required" example:"twilio"`
|
||||
}
|
||||
|
||||
// SendResetCode godoc
|
||||
|
|
@ -246,7 +240,7 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
|||
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
||||
}
|
||||
|
||||
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, req.Provider); err != nil {
|
||||
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
||||
h.logger.Error("Failed to send reset code", "error", err)
|
||||
fmt.Println(err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code")
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@ import (
|
|||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type UpdateWalletActiveReq struct {
|
||||
IsActive bool `json:"is_active" validate:"required" example:"true"`
|
||||
}
|
||||
type WalletRes struct {
|
||||
ID int64 `json:"id" example:"1"`
|
||||
Balance float32 `json:"amount" example:"100.0"`
|
||||
|
|
@ -45,9 +42,14 @@ type CustomerWalletRes struct {
|
|||
StaticID int64 `json:"static_id" example:"1"`
|
||||
StaticBalance float32 `json:"static_balance" example:"100.0"`
|
||||
CustomerID int64 `json:"customer_id" example:"1"`
|
||||
RegularIsActive bool `json:"regular_is_active" example:"true"`
|
||||
StaticIsActive bool `json:"static_is_active" example:"true"`
|
||||
RegularUpdatedAt time.Time `json:"regular_updated_at"`
|
||||
StaticUpdatedAt time.Time `json:"static_updated_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
FirstName string `json:"first_name" example:"John"`
|
||||
LastName string `json:"last_name" example:"Smith"`
|
||||
PhoneNumber string `json:"phone_number" example:"0911111111"`
|
||||
}
|
||||
|
||||
func ConvertCustomerWallet(wallet domain.GetCustomerWallet) CustomerWalletRes {
|
||||
|
|
@ -58,9 +60,14 @@ func ConvertCustomerWallet(wallet domain.GetCustomerWallet) CustomerWalletRes {
|
|||
StaticID: wallet.StaticID,
|
||||
StaticBalance: wallet.StaticBalance.Float32(),
|
||||
CustomerID: wallet.CustomerID,
|
||||
RegularIsActive: wallet.RegularIsActive,
|
||||
StaticIsActive: wallet.StaticIsActive,
|
||||
RegularUpdatedAt: wallet.RegularUpdatedAt,
|
||||
StaticUpdatedAt: wallet.StaticUpdatedAt,
|
||||
CreatedAt: wallet.CreatedAt,
|
||||
FirstName: wallet.FirstName,
|
||||
LastName: wallet.LastName,
|
||||
PhoneNumber: wallet.PhoneNumber,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +180,38 @@ func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All Wallets retrieved", res, nil)
|
||||
}
|
||||
|
||||
// GetAllCustomerWallets godoc
|
||||
// @Summary Get all customer wallets
|
||||
// @Description Retrieve all customer wallets
|
||||
// @Tags wallet
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} CustomerWalletRes
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /customerWallet [get]
|
||||
func (h *Handler) GetAllCustomerWallets(c *fiber.Ctx) error {
|
||||
|
||||
wallets, err := h.walletSvc.GetAllCustomerWallet(c.Context())
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get wallets", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
|
||||
}
|
||||
|
||||
var res []CustomerWalletRes = make([]CustomerWalletRes, 0, len(wallets))
|
||||
|
||||
for _, wallet := range wallets {
|
||||
res = append(res, ConvertCustomerWallet(wallet))
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "All Wallets retrieved", res, nil)
|
||||
}
|
||||
|
||||
type UpdateWalletActiveReq struct {
|
||||
IsActive bool `json:"is_active" validate:"required" example:"true"`
|
||||
}
|
||||
|
||||
// UpdateWalletActive godoc
|
||||
|
|
@ -255,13 +293,13 @@ func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
|
|||
|
||||
// h.logger.Info("Fetching customer wallet", "userID", userID)
|
||||
|
||||
wallet, err := h.walletSvc.GetWalletsByUser(c.Context(), userID)
|
||||
wallet, err := h.walletSvc.GetCustomerWallet(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get customer wallet", "userID", userID, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet")
|
||||
}
|
||||
|
||||
res := convertWallet(wallet[0])
|
||||
res := ConvertCustomerWallet(wallet)
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ func (a *App) initAppRoutes() {
|
|||
a.instSvc,
|
||||
a.currSvc,
|
||||
a.logger,
|
||||
a.settingSvc,
|
||||
a.NotidicationStore,
|
||||
a.validator,
|
||||
a.reportSvc,
|
||||
|
|
@ -55,7 +56,7 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Welcome to the FortuneBet API",
|
||||
"version": "1.0dev6",
|
||||
"version": "1.0dev7",
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -175,6 +176,7 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
|
||||
a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
|
||||
a.fiber.Get("/search/company", a.authMiddleware, h.SearchCompany)
|
||||
a.fiber.Get("/admin-company", a.authMiddleware, h.GetCompanyForAdmin)
|
||||
|
||||
// Ticket Routes
|
||||
a.fiber.Post("/ticket", h.CreateTicket)
|
||||
|
|
@ -196,6 +198,7 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/wallet/:id", h.GetWalletByID)
|
||||
a.fiber.Put("/wallet/:id", h.UpdateWalletActive)
|
||||
a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
|
||||
a.fiber.Get("/customerWallet", a.authMiddleware, h.GetAllCustomerWallets)
|
||||
a.fiber.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
|
||||
|
||||
// Transfer
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user