bet on same bet only twice
This commit is contained in:
parent
dc2144a91e
commit
78d351cae9
|
|
@ -55,6 +55,7 @@ CREATE TABLE IF NOT EXISTS bets (
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
is_shop_bet BOOLEAN NOT NULL,
|
is_shop_bet BOOLEAN NOT NULL,
|
||||||
|
outcomes_hash TEXT NOT NULL,
|
||||||
UNIQUE(cashout_id),
|
UNIQUE(cashout_id),
|
||||||
CHECK (
|
CHECK (
|
||||||
user_id IS NOT NULL
|
user_id IS NOT NULL
|
||||||
|
|
@ -310,7 +311,7 @@ ALTER TABLE bets
|
||||||
ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
ADD CONSTRAINT fk_bets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
ADD CONSTRAINT fk_bets_branches FOREIGN KEY (branch_id) REFERENCES branches(id);
|
ADD CONSTRAINT fk_bets_branches FOREIGN KEY (branch_id) REFERENCES branches(id);
|
||||||
ALTER TABLE wallets
|
ALTER TABLE wallets
|
||||||
ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id);
|
ADD CONSTRAINT fk_wallets_users FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB';
|
ADD COLUMN currency VARCHAR(3) NOT NULL DEFAULT 'ETB';
|
||||||
ALTER TABLE customer_wallets
|
ALTER TABLE customer_wallets
|
||||||
ADD CONSTRAINT fk_customer_wallets_customers FOREIGN KEY (customer_id) REFERENCES users(id),
|
ADD CONSTRAINT fk_customer_wallets_customers FOREIGN KEY (customer_id) REFERENCES users(id),
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ INSERT INTO bets (
|
||||||
user_id,
|
user_id,
|
||||||
is_shop_bet,
|
is_shop_bet,
|
||||||
cashout_id,
|
cashout_id,
|
||||||
company_id
|
company_id,
|
||||||
|
outcomes_hash
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
-- name: CreateBetOutcome :copyfrom
|
-- name: CreateBetOutcome :copyfrom
|
||||||
INSERT INTO bet_outcomes (
|
INSERT INTO bet_outcomes (
|
||||||
|
|
@ -83,6 +84,11 @@ WHERE event_id = $1;
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM bet_outcomes
|
FROM bet_outcomes
|
||||||
WHERE bet_id = $1;
|
WHERE bet_id = $1;
|
||||||
|
-- name: GetBetCount :one
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM bets
|
||||||
|
where user_id = $1
|
||||||
|
AND outcomes_hash = $2;
|
||||||
-- name: UpdateCashOut :exec
|
-- name: UpdateCashOut :exec
|
||||||
UPDATE bets
|
UPDATE bets
|
||||||
SET cashed_out = $2,
|
SET cashed_out = $2,
|
||||||
|
|
|
||||||
|
|
@ -22,23 +22,25 @@ INSERT INTO bets (
|
||||||
user_id,
|
user_id,
|
||||||
is_shop_bet,
|
is_shop_bet,
|
||||||
cashout_id,
|
cashout_id,
|
||||||
company_id
|
company_id,
|
||||||
|
outcomes_hash
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||||
RETURNING id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet
|
RETURNING id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateBetParams struct {
|
type CreateBetParams struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
PhoneNumber string `json:"phone_number"`
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
BranchID pgtype.Int8 `json:"branch_id"`
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
UserID pgtype.Int8 `json:"user_id"`
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
CashoutID string `json:"cashout_id"`
|
CashoutID string `json:"cashout_id"`
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
CompanyID pgtype.Int8 `json:"company_id"`
|
||||||
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, error) {
|
func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, error) {
|
||||||
|
|
@ -53,6 +55,7 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
|
||||||
arg.IsShopBet,
|
arg.IsShopBet,
|
||||||
arg.CashoutID,
|
arg.CashoutID,
|
||||||
arg.CompanyID,
|
arg.CompanyID,
|
||||||
|
arg.OutcomesHash,
|
||||||
)
|
)
|
||||||
var i Bet
|
var i Bet
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
|
@ -70,6 +73,7 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +115,7 @@ func (q *Queries) DeleteBetOutcome(ctx context.Context, betID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetAllBets = `-- name: GetAllBets :many
|
const GetAllBets = `-- name: GetAllBets :many
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
wHERE (
|
wHERE (
|
||||||
branch_id = $1
|
branch_id = $1
|
||||||
|
|
@ -157,6 +161,7 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -170,7 +175,7 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetBetByBranchID = `-- name: GetBetByBranchID :many
|
const GetBetByBranchID = `-- name: GetBetByBranchID :many
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE branch_id = $1
|
WHERE branch_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -199,6 +204,7 @@ func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -212,7 +218,7 @@ func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetBetByCashoutID = `-- name: GetBetByCashoutID :one
|
const GetBetByCashoutID = `-- name: GetBetByCashoutID :one
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE cashout_id = $1
|
WHERE cashout_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -235,13 +241,14 @@ func (q *Queries) GetBetByCashoutID(ctx context.Context, cashoutID string) (BetW
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetBetByID = `-- name: GetBetByID :one
|
const GetBetByID = `-- name: GetBetByID :one
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -264,13 +271,14 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetBetByUserID = `-- name: GetBetByUserID :many
|
const GetBetByUserID = `-- name: GetBetByUserID :many
|
||||||
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
|
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes_hash, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -299,6 +307,7 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -311,6 +320,25 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GetBetCount = `-- name: GetBetCount :one
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM bets
|
||||||
|
where user_id = $1
|
||||||
|
AND outcomes_hash = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetBetCountParams struct {
|
||||||
|
UserID pgtype.Int8 `json:"user_id"`
|
||||||
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetBetCount(ctx context.Context, arg GetBetCountParams) (int64, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetBetCount, arg.UserID, arg.OutcomesHash)
|
||||||
|
var count int64
|
||||||
|
err := row.Scan(&count)
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
const GetBetOutcomeByBetID = `-- name: GetBetOutcomeByBetID :many
|
const GetBetOutcomeByBetID = `-- name: GetBetOutcomeByBetID :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
|
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
|
FROM bet_outcomes
|
||||||
|
|
|
||||||
|
|
@ -56,20 +56,21 @@ func (ns NullReferralstatus) Value() (driver.Value, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bet struct {
|
type Bet struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
PhoneNumber string `json:"phone_number"`
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
CompanyID pgtype.Int8 `json:"company_id"`
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
BranchID pgtype.Int8 `json:"branch_id"`
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
UserID pgtype.Int8 `json:"user_id"`
|
||||||
CashedOut bool `json:"cashed_out"`
|
CashedOut bool `json:"cashed_out"`
|
||||||
CashoutID string `json:"cashout_id"`
|
CashoutID string `json:"cashout_id"`
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BetOutcome struct {
|
type BetOutcome struct {
|
||||||
|
|
@ -91,21 +92,22 @@ type BetOutcome struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BetWithOutcome struct {
|
type BetWithOutcome struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
TotalOdds float32 `json:"total_odds"`
|
TotalOdds float32 `json:"total_odds"`
|
||||||
Status int32 `json:"status"`
|
Status int32 `json:"status"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name"`
|
||||||
PhoneNumber string `json:"phone_number"`
|
PhoneNumber string `json:"phone_number"`
|
||||||
CompanyID pgtype.Int8 `json:"company_id"`
|
CompanyID pgtype.Int8 `json:"company_id"`
|
||||||
BranchID pgtype.Int8 `json:"branch_id"`
|
BranchID pgtype.Int8 `json:"branch_id"`
|
||||||
UserID pgtype.Int8 `json:"user_id"`
|
UserID pgtype.Int8 `json:"user_id"`
|
||||||
CashedOut bool `json:"cashed_out"`
|
CashedOut bool `json:"cashed_out"`
|
||||||
CashoutID string `json:"cashout_id"`
|
CashoutID string `json:"cashout_id"`
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
Outcomes []BetOutcome `json:"outcomes"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
|
Outcomes []BetOutcome `json:"outcomes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Branch struct {
|
type Branch struct {
|
||||||
|
|
@ -204,6 +206,15 @@ type Event struct {
|
||||||
Source pgtype.Text `json:"source"`
|
Source pgtype.Text `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExchangeRate struct {
|
||||||
|
ID int32 `json:"id"`
|
||||||
|
FromCurrency string `json:"from_currency"`
|
||||||
|
ToCurrency string `json:"to_currency"`
|
||||||
|
Rate pgtype.Numeric `json:"rate"`
|
||||||
|
ValidUntil pgtype.Timestamp `json:"valid_until"`
|
||||||
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
type League struct {
|
type League struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
@ -470,6 +481,7 @@ type Wallet struct {
|
||||||
IsActive bool `json:"is_active"`
|
IsActive bool `json:"is_active"`
|
||||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
BonusBalance pgtype.Numeric `json:"bonus_balance"`
|
BonusBalance pgtype.Numeric `json:"bonus_balance"`
|
||||||
CashBalance pgtype.Numeric `json:"cash_balance"`
|
CashBalance pgtype.Numeric `json:"cash_balance"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ INSERT INTO wallets (
|
||||||
user_id
|
user_id
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4)
|
VALUES ($1, $2, $3, $4)
|
||||||
RETURNING id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, bonus_balance, cash_balance
|
RETURNING id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, currency, bonus_balance, cash_balance
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateWalletParams struct {
|
type CreateWalletParams struct {
|
||||||
|
|
@ -77,6 +77,7 @@ func (q *Queries) CreateWallet(ctx context.Context, arg CreateWalletParams) (Wal
|
||||||
&i.IsActive,
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
|
&i.Currency,
|
||||||
&i.BonusBalance,
|
&i.BonusBalance,
|
||||||
&i.CashBalance,
|
&i.CashBalance,
|
||||||
)
|
)
|
||||||
|
|
@ -143,7 +144,7 @@ func (q *Queries) GetAllBranchWallets(ctx context.Context) ([]GetAllBranchWallet
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetAllWallets = `-- name: GetAllWallets :many
|
const GetAllWallets = `-- name: GetAllWallets :many
|
||||||
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, bonus_balance, cash_balance
|
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, currency, bonus_balance, cash_balance
|
||||||
FROM wallets
|
FROM wallets
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -166,6 +167,7 @@ func (q *Queries) GetAllWallets(ctx context.Context) ([]Wallet, error) {
|
||||||
&i.IsActive,
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
|
&i.Currency,
|
||||||
&i.BonusBalance,
|
&i.BonusBalance,
|
||||||
&i.CashBalance,
|
&i.CashBalance,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
|
|
@ -225,7 +227,7 @@ func (q *Queries) GetCustomerWallet(ctx context.Context, customerID int64) (GetC
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetWalletByID = `-- name: GetWalletByID :one
|
const GetWalletByID = `-- name: GetWalletByID :one
|
||||||
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, bonus_balance, cash_balance
|
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, currency, bonus_balance, cash_balance
|
||||||
FROM wallets
|
FROM wallets
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -243,6 +245,7 @@ func (q *Queries) GetWalletByID(ctx context.Context, id int64) (Wallet, error) {
|
||||||
&i.IsActive,
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
|
&i.Currency,
|
||||||
&i.BonusBalance,
|
&i.BonusBalance,
|
||||||
&i.CashBalance,
|
&i.CashBalance,
|
||||||
)
|
)
|
||||||
|
|
@ -250,7 +253,7 @@ func (q *Queries) GetWalletByID(ctx context.Context, id int64) (Wallet, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetWalletByUserID = `-- name: GetWalletByUserID :many
|
const GetWalletByUserID = `-- name: GetWalletByUserID :many
|
||||||
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, bonus_balance, cash_balance
|
SELECT id, balance, is_withdraw, is_bettable, is_transferable, user_id, is_active, created_at, updated_at, currency, bonus_balance, cash_balance
|
||||||
FROM wallets
|
FROM wallets
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -274,6 +277,7 @@ func (q *Queries) GetWalletByUserID(ctx context.Context, userID int64) ([]Wallet
|
||||||
&i.IsActive,
|
&i.IsActive,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
|
&i.Currency,
|
||||||
&i.BonusBalance,
|
&i.BonusBalance,
|
||||||
&i.CashBalance,
|
&i.CashBalance,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -80,16 +80,17 @@ type GetBet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateBet struct {
|
type CreateBet struct {
|
||||||
Amount Currency
|
Amount Currency
|
||||||
TotalOdds float32
|
TotalOdds float32
|
||||||
Status OutcomeStatus
|
Status OutcomeStatus
|
||||||
FullName string
|
FullName string
|
||||||
PhoneNumber string
|
PhoneNumber string
|
||||||
CompanyID ValidInt64 // Can Be Nullable
|
CompanyID ValidInt64 // Can Be Nullable
|
||||||
BranchID ValidInt64 // Can Be Nullable
|
BranchID ValidInt64 // Can Be Nullable
|
||||||
UserID ValidInt64 // Can Be Nullable
|
UserID ValidInt64 // Can Be Nullable
|
||||||
IsShopBet bool
|
IsShopBet bool
|
||||||
CashoutID string
|
CashoutID string
|
||||||
|
OutcomesHash string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateBetOutcomeReq struct {
|
type CreateBetOutcomeReq struct {
|
||||||
|
|
@ -173,4 +174,3 @@ func ConvertBet(bet GetBet) BetRes {
|
||||||
CreatedAt: bet.CreatedAt,
|
CreatedAt: bet.CreatedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,19 @@ func (s *Store) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetB
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||||
|
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
||||||
|
UserID: pgtype.Int8{Int64: UserID},
|
||||||
|
OutcomesHash: outcomesHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error {
|
func (s *Store) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error {
|
||||||
err := s.queries.UpdateCashOut(ctx, dbgen.UpdateCashOutParams{
|
err := s.queries.UpdateCashOut(ctx, dbgen.UpdateCashOutParams{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ type BetStore interface {
|
||||||
GetBetByUserID(ctx context.Context, UserID 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) ([]domain.BetOutcome, error)
|
||||||
GetBetOutcomeByBetID(ctx context.Context, betID int64) ([]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
|
UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error
|
||||||
UpdateStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error
|
UpdateStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error
|
||||||
UpdateBetOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
UpdateBetOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) (domain.BetOutcome, error)
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,17 @@ package bet
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math/big"
|
"math/big"
|
||||||
random "math/rand"
|
random "math/rand"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
|
|
@ -196,6 +200,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
var totalOdds float32 = 1
|
var totalOdds float32 = 1
|
||||||
|
|
||||||
for _, outcomeReq := range req.Outcomes {
|
for _, outcomeReq := range req.Outcomes {
|
||||||
|
fmt.Println("reqq: ", outcomeReq)
|
||||||
newOutcome, err := s.GenerateBetOutcome(ctx, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID)
|
newOutcome, err := s.GenerateBetOutcome(ctx, outcomeReq.EventID, outcomeReq.MarketID, outcomeReq.OddID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to generate outcome",
|
s.mongoLogger.Error("failed to generate outcome",
|
||||||
|
|
@ -211,6 +216,23 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
outcomes = append(outcomes, newOutcome)
|
outcomes = append(outcomes, newOutcome)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outcomesHash, err := generateOutcomeHash(outcomes)
|
||||||
|
if err != nil {
|
||||||
|
s.mongoLogger.Error("failed to generate outcome hash",
|
||||||
|
zap.Int64("user_id", userID),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return domain.CreateBetRes{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||||
|
if err != nil {
|
||||||
|
return domain.CreateBetRes{}, err
|
||||||
|
}
|
||||||
|
if count == 2 {
|
||||||
|
return domain.CreateBetRes{}, fmt.Errorf("bet already pleaced twice")
|
||||||
|
}
|
||||||
|
|
||||||
cashoutID, err := s.GenerateCashoutID()
|
cashoutID, err := s.GenerateCashoutID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to generate cashout ID",
|
s.mongoLogger.Error("failed to generate cashout ID",
|
||||||
|
|
@ -221,12 +243,13 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
}
|
}
|
||||||
|
|
||||||
newBet := domain.CreateBet{
|
newBet := domain.CreateBet{
|
||||||
Amount: domain.ToCurrency(req.Amount),
|
Amount: domain.ToCurrency(req.Amount),
|
||||||
TotalOdds: totalOdds,
|
TotalOdds: totalOdds,
|
||||||
Status: req.Status,
|
Status: req.Status,
|
||||||
FullName: req.FullName,
|
FullName: req.FullName,
|
||||||
PhoneNumber: req.PhoneNumber,
|
PhoneNumber: req.PhoneNumber,
|
||||||
CashoutID: cashoutID,
|
CashoutID: cashoutID,
|
||||||
|
OutcomesHash: outcomesHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch role {
|
switch role {
|
||||||
|
|
@ -321,6 +344,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
||||||
return domain.CreateBetRes{}, fmt.Errorf("Unknown Role Type")
|
return domain.CreateBetRes{}, fmt.Errorf("Unknown Role Type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Bet is: ", newBet)
|
||||||
bet, err := s.CreateBet(ctx, newBet)
|
bet, err := s.CreateBet(ctx, newBet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.mongoLogger.Error("failed to create bet",
|
s.mongoLogger.Error("failed to create bet",
|
||||||
|
|
@ -636,6 +660,10 @@ func (s *Service) GetBetByUserID(ctx context.Context, UserID int64) ([]domain.Ge
|
||||||
return s.betStore.GetBetByUserID(ctx, UserID)
|
return s.betStore.GetBetByUserID(ctx, UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||||
|
return s.betStore.GetBetCount(ctx, UserID, outcomesHash)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error {
|
func (s *Service) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error {
|
||||||
return s.betStore.UpdateCashOut(ctx, id, cashedOut)
|
return s.betStore.UpdateCashOut(ctx, id, cashedOut)
|
||||||
}
|
}
|
||||||
|
|
@ -785,3 +813,24 @@ func (s *Service) UpdateBetOutcomeStatus(ctx context.Context, id int64, status d
|
||||||
func (s *Service) DeleteBet(ctx context.Context, id int64) error {
|
func (s *Service) DeleteBet(ctx context.Context, id int64) error {
|
||||||
return s.betStore.DeleteBet(ctx, id)
|
return s.betStore.DeleteBet(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
||||||
|
// should always be in the same order for producing the same hash
|
||||||
|
sort.Slice(outcomes, func(i, j int) bool {
|
||||||
|
if outcomes[i].EventID != outcomes[j].EventID {
|
||||||
|
return outcomes[i].EventID < outcomes[j].EventID
|
||||||
|
}
|
||||||
|
if outcomes[i].MarketID != outcomes[j].MarketID {
|
||||||
|
return outcomes[i].MarketID < outcomes[j].MarketID
|
||||||
|
}
|
||||||
|
return outcomes[i].OddID < outcomes[j].OddID
|
||||||
|
})
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
for _, o := range outcomes {
|
||||||
|
sb.WriteString(fmt.Sprintf("%d-%d-%d;", o.EventID, o.MarketID, o.OddID))
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := sha256.Sum256([]byte(sb.String()))
|
||||||
|
return hex.EncodeToString(sum[:]), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.betSvc.
|
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role)
|
||||||
PlaceBet(c.Context(), req, userID, role)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.Error("PlaceBet failed", "error", err)
|
h.logger.Error("PlaceBet failed", "error", err)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user