Merge branch 'cashback'
This commit is contained in:
commit
fd55639c02
|
|
@ -168,6 +168,7 @@ func main() {
|
||||||
)
|
)
|
||||||
|
|
||||||
go httpserver.SetupReportCronJobs(context.Background(), reportSvc)
|
go httpserver.SetupReportCronJobs(context.Background(), reportSvc)
|
||||||
|
go httpserver.ProcessBetCashback(context.TODO(), betSvc)
|
||||||
|
|
||||||
bankRepository := repository.NewBankRepository(store)
|
bankRepository := repository.NewBankRepository(store)
|
||||||
instSvc := institutions.New(bankRepository)
|
instSvc := institutions.New(bankRepository)
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ CREATE TABLE IF NOT EXISTS bets (
|
||||||
is_shop_bet BOOLEAN NOT NULL,
|
is_shop_bet BOOLEAN NOT NULL,
|
||||||
outcomes_hash TEXT NOT NULL,
|
outcomes_hash TEXT NOT NULL,
|
||||||
fast_code VARCHAR(10) NOT NULL,
|
fast_code VARCHAR(10) NOT NULL,
|
||||||
|
processed BOOLEAN DEFAULT FALSE NOT NULL,
|
||||||
UNIQUE(cashout_id),
|
UNIQUE(cashout_id),
|
||||||
CHECK (
|
CHECK (
|
||||||
user_id IS NOT NULL
|
user_id IS NOT NULL
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,11 @@ SELECT *
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE fast_code = $1
|
WHERE fast_code = $1
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
-- name: GetBetsForCashback :many
|
||||||
|
SELECT *
|
||||||
|
FROM bet_with_outcomes
|
||||||
|
WHERE status = 2
|
||||||
|
AND processed = false;
|
||||||
-- name: GetBetOutcomeByEventID :many
|
-- name: GetBetOutcomeByEventID :many
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM bet_outcomes
|
FROM bet_outcomes
|
||||||
|
|
@ -143,6 +148,10 @@ UPDATE bets
|
||||||
SET status = $1,
|
SET status = $1,
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE id = $2;
|
WHERE id = $2;
|
||||||
|
-- name: UpdateBetWithCashback :exec
|
||||||
|
UPDATE bets
|
||||||
|
SET processed = $1
|
||||||
|
WHERE id = $2;
|
||||||
-- name: DeleteBet :exec
|
-- name: DeleteBet :exec
|
||||||
DELETE FROM bets
|
DELETE FROM bets
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ INSERT INTO bets (
|
||||||
fast_code
|
fast_code
|
||||||
)
|
)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||||
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, fast_code
|
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, fast_code, processed
|
||||||
`
|
`
|
||||||
|
|
||||||
type CreateBetParams struct {
|
type CreateBetParams struct {
|
||||||
|
|
@ -78,6 +78,7 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +120,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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
wHERE (
|
wHERE (
|
||||||
branch_id = $1
|
branch_id = $1
|
||||||
|
|
@ -196,6 +197,7 @@ func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWi
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -209,7 +211,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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE branch_id = $1
|
WHERE branch_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -240,6 +242,7 @@ func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -253,7 +256,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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE cashout_id = $1
|
WHERE cashout_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -278,13 +281,14 @@ func (q *Queries) GetBetByCashoutID(ctx context.Context, cashoutID string) (BetW
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const GetBetByFastCode = `-- name: GetBetByFastCode :one
|
const GetBetByFastCode = `-- name: GetBetByFastCode :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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE fast_code = $1
|
WHERE fast_code = $1
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
|
|
@ -310,13 +314,14 @@ func (q *Queries) GetBetByFastCode(ctx context.Context, fastCode string) (BetWit
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -341,13 +346,14 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&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_hash, fast_code, 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, fast_code, processed, outcomes
|
||||||
FROM bet_with_outcomes
|
FROM bet_with_outcomes
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
`
|
`
|
||||||
|
|
@ -378,6 +384,7 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
&i.IsShopBet,
|
&i.IsShopBet,
|
||||||
&i.OutcomesHash,
|
&i.OutcomesHash,
|
||||||
&i.FastCode,
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
&i.Outcomes,
|
&i.Outcomes,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -393,7 +400,7 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
|
||||||
const GetBetCount = `-- name: GetBetCount :one
|
const GetBetCount = `-- name: GetBetCount :one
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM bets
|
FROM bets
|
||||||
where user_id = $1
|
WHERE user_id = $1
|
||||||
AND outcomes_hash = $2
|
AND outcomes_hash = $2
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -505,6 +512,52 @@ func (q *Queries) GetBetOutcomeByEventID(ctx context.Context, arg GetBetOutcomeB
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GetBetsForCashback = `-- name: GetBetsForCashback :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_hash, fast_code, processed, outcomes
|
||||||
|
FROM bet_with_outcomes
|
||||||
|
WHERE status = 2
|
||||||
|
AND processed = false
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetBetsForCashback(ctx context.Context) ([]BetWithOutcome, error) {
|
||||||
|
rows, err := q.db.Query(ctx, GetBetsForCashback)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []BetWithOutcome
|
||||||
|
for rows.Next() {
|
||||||
|
var i BetWithOutcome
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Amount,
|
||||||
|
&i.TotalOdds,
|
||||||
|
&i.Status,
|
||||||
|
&i.FullName,
|
||||||
|
&i.PhoneNumber,
|
||||||
|
&i.CompanyID,
|
||||||
|
&i.BranchID,
|
||||||
|
&i.UserID,
|
||||||
|
&i.CashedOut,
|
||||||
|
&i.CashoutID,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
&i.IsShopBet,
|
||||||
|
&i.OutcomesHash,
|
||||||
|
&i.FastCode,
|
||||||
|
&i.Processed,
|
||||||
|
&i.Outcomes,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
const UpdateBetOutcomeStatus = `-- name: UpdateBetOutcomeStatus :one
|
const UpdateBetOutcomeStatus = `-- name: UpdateBetOutcomeStatus :one
|
||||||
UPDATE bet_outcomes
|
UPDATE bet_outcomes
|
||||||
SET status = $1
|
SET status = $1
|
||||||
|
|
@ -623,6 +676,22 @@ func (q *Queries) UpdateBetOutcomeStatusForEvent(ctx context.Context, arg Update
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UpdateBetWithCashback = `-- name: UpdateBetWithCashback :exec
|
||||||
|
UPDATE bets
|
||||||
|
SET processed = $1
|
||||||
|
WHERE id = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateBetWithCashbackParams struct {
|
||||||
|
Processed bool `json:"processed"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateBetWithCashback(ctx context.Context, arg UpdateBetWithCashbackParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, UpdateBetWithCashback, arg.Processed, arg.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const UpdateCashOut = `-- name: UpdateCashOut :exec
|
const UpdateCashOut = `-- name: UpdateCashOut :exec
|
||||||
UPDATE bets
|
UPDATE bets
|
||||||
SET cashed_out = $2,
|
SET cashed_out = $2,
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ type Bet struct {
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
FastCode string `json:"fast_code"`
|
FastCode string `json:"fast_code"`
|
||||||
|
Processed bool `json:"processed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BetOutcome struct {
|
type BetOutcome struct {
|
||||||
|
|
@ -127,6 +128,7 @@ type BetWithOutcome struct {
|
||||||
IsShopBet bool `json:"is_shop_bet"`
|
IsShopBet bool `json:"is_shop_bet"`
|
||||||
OutcomesHash string `json:"outcomes_hash"`
|
OutcomesHash string `json:"outcomes_hash"`
|
||||||
FastCode string `json:"fast_code"`
|
FastCode string `json:"fast_code"`
|
||||||
|
Processed bool `json:"processed"`
|
||||||
Outcomes []BetOutcome `json:"outcomes"`
|
Outcomes []BetOutcome `json:"outcomes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,22 @@ func (s *Store) GetBetByFastCode(ctx context.Context, fastcode string) (domain.G
|
||||||
return convertDBBetWithOutcomes(bet), nil
|
return convertDBBetWithOutcomes(bet), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error) {
|
||||||
|
bets, err := s.queries.GetBetsForCashback(ctx)
|
||||||
|
var res []domain.GetBet
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bet := range bets {
|
||||||
|
cashbackBet := convertDBBetWithOutcomes(bet)
|
||||||
|
res = append(res, cashbackBet)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||||
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
||||||
UserID: pgtype.Int8{Int64: UserID, Valid: true},
|
UserID: pgtype.Int8{Int64: UserID, Valid: true},
|
||||||
|
|
@ -439,6 +455,24 @@ func (s *Store) UpdateBetOutcomeStatusForEvent(ctx context.Context, eventID int6
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error {
|
||||||
|
err := s.queries.UpdateBetWithCashback(ctx, dbgen.UpdateBetWithCashbackParams{
|
||||||
|
ID: betID,
|
||||||
|
Processed: cashbackStatus,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
domain.MongoDBLogger.Error("failed to update bet outcome status for event",
|
||||||
|
zap.Int64("betID", betID),
|
||||||
|
zap.Bool("status", cashbackStatus),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBetSummary returns aggregated bet statistics
|
// GetBetSummary returns aggregated bet statistics
|
||||||
func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
func (s *Store) GetBetSummary(ctx context.Context, filter domain.ReportFilter) (
|
||||||
totalStakes domain.Currency,
|
totalStakes domain.Currency,
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,7 @@ type BetStore interface {
|
||||||
GetSportBetActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.SportBetActivity, error)
|
GetSportBetActivity(ctx context.Context, filter domain.ReportFilter) ([]domain.SportBetActivity, error)
|
||||||
GetSportDetails(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
|
GetSportDetails(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
|
||||||
GetSportMarketPopularity(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
|
GetSportMarketPopularity(ctx context.Context, filter domain.ReportFilter) (map[string]string, error)
|
||||||
|
|
||||||
|
GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error)
|
||||||
|
UpdateBetWithCashback(ctx context.Context, betID int64, cashbackStatus bool) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
random "math/rand"
|
random "math/rand"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
@ -907,6 +908,71 @@ func (s *Service) SetBetToRemoved(ctx context.Context, id int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) ProcessBetCashback(ctx context.Context) error {
|
||||||
|
bets, err := s.betStore.GetBetsForCashback(ctx)
|
||||||
|
if err != nil {
|
||||||
|
s.mongoLogger.Error("failed to fetch bets",
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bet := range bets {
|
||||||
|
shouldProcess := true
|
||||||
|
loseCount := 0
|
||||||
|
|
||||||
|
for _, outcome := range bet.Outcomes {
|
||||||
|
// stop if other outcomes exists in bet outcomes
|
||||||
|
if outcome.Status != domain.OUTCOME_STATUS_LOSS && outcome.Status != domain.OUTCOME_STATUS_WIN {
|
||||||
|
shouldProcess = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if outcome.Status == domain.OUTCOME_STATUS_LOSS {
|
||||||
|
loseCount++
|
||||||
|
// only process caseback if bet is lost by one
|
||||||
|
if loseCount > 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldProcess || loseCount != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.betStore.UpdateBetWithCashback(ctx, bet.ID, true); err != nil {
|
||||||
|
s.mongoLogger.Error("failed to process cashback for bet",
|
||||||
|
zap.Int64("betID", bet.ID),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wallets, err := s.walletSvc.GetCustomerWallet(ctx, bet.UserID.Value)
|
||||||
|
if err != nil {
|
||||||
|
s.mongoLogger.Error("failed to get wallets of a user",
|
||||||
|
zap.Int64("userID", bet.UserID.Value),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: get cashback amount cap (currently 1000) from settings in the db
|
||||||
|
cashbackAmount := math.Min(10, float64(calculateCashbackAmount(bet.Amount.Float32(), bet.TotalOdds)))
|
||||||
|
|
||||||
|
_, err = s.walletSvc.AddToWallet(ctx, wallets.StaticID, domain.ToCurrency(float32(cashbackAmount)), domain.ValidInt64{}, domain.TRANSFER_DIRECT,
|
||||||
|
domain.PaymentDetails{}, fmt.Sprintf("cashback amount of %f added to users static wallet", cashbackAmount))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.mongoLogger.Error("Failed to update wallet for user",
|
||||||
|
zap.Int64("userID", bet.UserID.Value),
|
||||||
|
zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
||||||
// should always be in the same order for producing the same hash
|
// should always be in the same order for producing the same hash
|
||||||
sort.Slice(outcomes, func(i, j int) bool {
|
sort.Slice(outcomes, func(i, j int) bool {
|
||||||
|
|
@ -927,3 +993,29 @@ func generateOutcomeHash(outcomes []domain.CreateBetOutcome) (string, error) {
|
||||||
sum := sha256.Sum256([]byte(sb.String()))
|
sum := sha256.Sum256([]byte(sb.String()))
|
||||||
return hex.EncodeToString(sum[:]), nil
|
return hex.EncodeToString(sum[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calculateCashbackAmount(amount, total_odds float32) float32 {
|
||||||
|
var multiplier float32
|
||||||
|
|
||||||
|
if total_odds < 18 {
|
||||||
|
multiplier = 0
|
||||||
|
} else if total_odds >= 18 && total_odds <= 35 {
|
||||||
|
multiplier = 1
|
||||||
|
} else if total_odds > 35 && total_odds <= 55 {
|
||||||
|
multiplier = 2
|
||||||
|
} else if total_odds > 55 && total_odds <= 95 {
|
||||||
|
multiplier = 3
|
||||||
|
} else if total_odds > 95 && total_odds <= 250 {
|
||||||
|
multiplier = 5
|
||||||
|
} else if total_odds > 250 && total_odds <= 450 {
|
||||||
|
multiplier = 10
|
||||||
|
} else if total_odds > 450 && total_odds <= 1000 {
|
||||||
|
multiplier = 50
|
||||||
|
} else if total_odds > 1000 && total_odds <= 2000 {
|
||||||
|
multiplier = 100
|
||||||
|
} else {
|
||||||
|
multiplier = 500
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount * multiplier
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
// "time"
|
// "time"
|
||||||
|
|
||||||
|
betSvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||||
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||||
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/report"
|
||||||
|
|
@ -148,3 +149,34 @@ func SetupReportCronJobs(ctx context.Context, reportService *report.Service) {
|
||||||
c.Start()
|
c.Start()
|
||||||
log.Println("Cron jobs started for report generation service")
|
log.Println("Cron jobs started for report generation service")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ProcessBetCashback(ctx context.Context, betService *betSvc.Service) {
|
||||||
|
c := cron.New(cron.WithSeconds())
|
||||||
|
|
||||||
|
schedule := []struct {
|
||||||
|
spec string
|
||||||
|
task func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
spec: "*/10 * * * * *", // 10 seconds for testing
|
||||||
|
// spec: "0 0 0 * * *", // Daily at midnight
|
||||||
|
task: func() {
|
||||||
|
log.Println("process bet cashbacks...")
|
||||||
|
if err := betService.ProcessBetCashback(ctx); err != nil {
|
||||||
|
log.Printf("Failed to process bet cashbacks: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Successfully processed bet cashbacks")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, job := range schedule {
|
||||||
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||||||
|
log.Fatalf("Failed to schedule cron job: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Start()
|
||||||
|
log.Println("Cron jobs started for bet cashbacks")
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user