flag too many outcomes
This commit is contained in:
parent
ae56d253c2
commit
e3545f3f8c
|
|
@ -79,4 +79,6 @@ DROP TABLE IF EXISTS events;
|
|||
DROP TABLE IF EXISTS leagues;
|
||||
DROP TABLE IF EXISTS teams;
|
||||
DROP TABLE IF EXISTS settings;
|
||||
DROP TABLE IF EXISTS bonus;
|
||||
DROP TABLE IF EXISTS flags;
|
||||
-- DELETE FROM wallet_transfer;
|
||||
|
|
@ -208,7 +208,7 @@ CREATE TABLE IF NOT EXISTS branches (
|
|||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
location TEXT NOT NULL,
|
||||
profit_percent REAL NOt NULL,
|
||||
profit_percent REAL NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT false,
|
||||
wallet_id BIGINT NOT NULL,
|
||||
branch_manager_id BIGINT NOT NULL,
|
||||
|
|
@ -319,6 +319,21 @@ CREATE TABLE bonus (
|
|||
multiplier REAL NOT NULL,
|
||||
balance_cap BIGINT NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE flags (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
bet_id BIGINT REFERENCES bets(id) ON DELETE CASCADE,
|
||||
odd_id BIGINT REFERENCES odds(id),
|
||||
reason TEXT,
|
||||
flagged_at TIMESTAMP DEFAULT NOW(),
|
||||
resolved BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- either bet or odd is flagged (not at the same time)
|
||||
CHECK (
|
||||
(bet_id IS NOT NULL AND odd_id IS NULL)
|
||||
OR
|
||||
(bet_id IS NULL AND odd_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
-- Views
|
||||
CREATE VIEW companies_details AS
|
||||
SELECT companies.*,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ VALUES ('max_number_of_outcomes', '30'),
|
|||
('bet_amount_limit', '100000'),
|
||||
('daily_ticket_limit', '50'),
|
||||
('total_winnings_limit', '1000000'),
|
||||
('amount_for_bet_referral', '1000000')
|
||||
('amount_for_bet_referral', '1000000'),
|
||||
('cashback_amount_cap', '1000')
|
||||
ON CONFLICT (key) DO
|
||||
UPDATE
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ WHERE (event_id = $1)
|
|||
SELECT *
|
||||
FROM bet_outcomes
|
||||
WHERE bet_id = $1;
|
||||
-- name: GetBetCount :one
|
||||
-- name: GetBetCountByUserID :one
|
||||
SELECT COUNT(*)
|
||||
FROM bets
|
||||
WHERE user_id = $1
|
||||
|
|
|
|||
8
db/query/flags.sql
Normal file
8
db/query/flags.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-- name: CreateFlag :one
|
||||
INSERT INTO flags (
|
||||
bet_id,
|
||||
odd_id,
|
||||
reason
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
) RETURNING *;
|
||||
|
|
@ -282,20 +282,20 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID int64) ([]BetWithOu
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const GetBetCount = `-- name: GetBetCount :one
|
||||
const GetBetCountByUserID = `-- name: GetBetCountByUserID :one
|
||||
SELECT COUNT(*)
|
||||
FROM bets
|
||||
WHERE user_id = $1
|
||||
AND outcomes_hash = $2
|
||||
`
|
||||
|
||||
type GetBetCountParams struct {
|
||||
type GetBetCountByUserIDParams struct {
|
||||
UserID int64 `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)
|
||||
func (q *Queries) GetBetCountByUserID(ctx context.Context, arg GetBetCountByUserIDParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, GetBetCountByUserID, arg.UserID, arg.OutcomesHash)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
|
|
|
|||
42
gen/db/flags.sql.go
Normal file
42
gen/db/flags.sql.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
// source: flags.sql
|
||||
|
||||
package dbgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const CreateFlag = `-- name: CreateFlag :one
|
||||
INSERT INTO flags (
|
||||
bet_id,
|
||||
odd_id,
|
||||
reason
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
) RETURNING id, bet_id, odd_id, reason, flagged_at, resolved
|
||||
`
|
||||
|
||||
type CreateFlagParams struct {
|
||||
BetID pgtype.Int8 `json:"bet_id"`
|
||||
OddID pgtype.Int8 `json:"odd_id"`
|
||||
Reason pgtype.Text `json:"reason"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateFlag(ctx context.Context, arg CreateFlagParams) (Flag, error) {
|
||||
row := q.db.QueryRow(ctx, CreateFlag, arg.BetID, arg.OddID, arg.Reason)
|
||||
var i Flag
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.BetID,
|
||||
&i.OddID,
|
||||
&i.Reason,
|
||||
&i.FlaggedAt,
|
||||
&i.Resolved,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -276,6 +276,15 @@ type FavoriteGame struct {
|
|||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
}
|
||||
|
||||
type Flag struct {
|
||||
ID int64 `json:"id"`
|
||||
BetID pgtype.Int8 `json:"bet_id"`
|
||||
OddID pgtype.Int8 `json:"odd_id"`
|
||||
Reason pgtype.Text `json:"reason"`
|
||||
FlaggedAt pgtype.Timestamp `json:"flagged_at"`
|
||||
Resolved pgtype.Bool `json:"resolved"`
|
||||
}
|
||||
|
||||
type League struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ type BetFilter struct {
|
|||
CreatedAfter ValidTime
|
||||
}
|
||||
|
||||
type Flag struct {
|
||||
ID int64
|
||||
BetID int64
|
||||
OddID int64
|
||||
Reason string
|
||||
FlaggedAt time.Time
|
||||
Resolved bool
|
||||
}
|
||||
|
||||
type GetBet struct {
|
||||
ID int64
|
||||
Amount Currency
|
||||
|
|
@ -93,17 +102,23 @@ type CreateBetOutcomeReq struct {
|
|||
}
|
||||
|
||||
type CreateBetReq struct {
|
||||
Outcomes []CreateBetOutcomeReq `json:"outcomes" validate:"required"`
|
||||
Amount float32 `json:"amount" validate:"required,gt=0" example:"100.0"`
|
||||
BranchID *int64 `json:"branch_id,omitempty" validate:"required" example:"1"`
|
||||
Outcomes []CreateBetOutcomeReq `json:"outcomes" validate:"required"`
|
||||
Amount float32 `json:"amount" validate:"required,gt=0" example:"100.0"`
|
||||
BranchID *int64 `json:"branch_id,omitempty" validate:"required" example:"1"`
|
||||
}
|
||||
|
||||
type CreateBetWithFastCodeReq struct {
|
||||
type CreateBetWithFastCodeReq struct {
|
||||
FastCode string `json:"fast_code"`
|
||||
Amount float32 `json:"amount"`
|
||||
BranchID *int64 `json:"branch_id"`
|
||||
}
|
||||
|
||||
type CreateFlagReq struct {
|
||||
BetID int64
|
||||
OddID int64
|
||||
Reason string
|
||||
}
|
||||
|
||||
type RandomBetReq struct {
|
||||
BranchID int64 `json:"branch_id" validate:"required" example:"1"`
|
||||
NumberOfBets int64 `json:"number_of_bets" validate:"required" example:"1"`
|
||||
|
|
|
|||
|
|
@ -76,6 +76,17 @@ func convertDBBetWithOutcomes(bet dbgen.BetWithOutcome) domain.GetBet {
|
|||
}
|
||||
}
|
||||
|
||||
func convertDBFlag(flag dbgen.Flag) domain.Flag {
|
||||
return domain.Flag{
|
||||
ID: flag.ID,
|
||||
BetID: flag.BetID.Int64,
|
||||
OddID: flag.OddID.Int64,
|
||||
Reason: flag.Reason.String,
|
||||
FlaggedAt: flag.FlaggedAt.Time,
|
||||
Resolved: flag.Resolved.Bool,
|
||||
}
|
||||
}
|
||||
|
||||
func convertDBCreateBetOutcome(betOutcome domain.CreateBetOutcome) dbgen.CreateBetOutcomeParams {
|
||||
return dbgen.CreateBetOutcomeParams{
|
||||
BetID: betOutcome.BetID,
|
||||
|
|
@ -140,6 +151,35 @@ func (s *Store) CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBe
|
|||
return rows, nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateFlag(ctx context.Context, flag domain.CreateFlagReq) (domain.Flag, error) {
|
||||
createFlag := dbgen.CreateFlagParams{
|
||||
BetID: pgtype.Int8{
|
||||
Int64: flag.BetID,
|
||||
Valid: flag.BetID != 0,
|
||||
},
|
||||
OddID: pgtype.Int8{
|
||||
Int64: flag.OddID,
|
||||
Valid: flag.OddID != 0,
|
||||
},
|
||||
Reason: pgtype.Text{
|
||||
String: flag.Reason,
|
||||
Valid: true,
|
||||
},
|
||||
}
|
||||
|
||||
f, err := s.queries.CreateFlag(ctx, createFlag)
|
||||
if err != nil {
|
||||
domain.MongoDBLogger.Error("failed to create flag",
|
||||
zap.String("flag", f.Reason.String),
|
||||
zap.Any("flag_id", f.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.Flag{}, err
|
||||
}
|
||||
|
||||
return convertDBFlag(f), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetBetByID(ctx context.Context, id int64) (domain.GetBet, error) {
|
||||
bet, err := s.queries.GetBetByID(ctx, id)
|
||||
if err != nil {
|
||||
|
|
@ -237,8 +277,8 @@ func (s *Store) GetBetsForCashback(ctx context.Context) ([]domain.GetBet, error)
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||
count, err := s.queries.GetBetCount(ctx, dbgen.GetBetCountParams{
|
||||
func (s *Store) GetBetCountByUserID(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||
count, err := s.queries.GetBetCountByUserID(ctx, dbgen.GetBetCountByUserIDParams{
|
||||
UserID: UserID,
|
||||
OutcomesHash: outcomesHash,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ import (
|
|||
type BetStore interface {
|
||||
CreateBet(ctx context.Context, bet domain.CreateBet) (domain.Bet, error)
|
||||
CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBetOutcome) (int64, error)
|
||||
CreateFlag(ctx context.Context, flag domain.CreateFlagReq) (domain.Flag, error)
|
||||
GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
|
||||
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error)
|
||||
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
|
||||
GetBetByFastCode(ctx context.Context, fastcode string) (domain.GetBet, 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)
|
||||
GetBetCountByUserID(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)
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||
count, err := s.GetBetCountByUserID(ctx, userID, outcomesHash)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to generate cashout ID",
|
||||
zap.Int64("user_id", userID),
|
||||
|
|
@ -360,15 +360,15 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
case domain.RoleCustomer:
|
||||
// Only the customer is able to create a online bet
|
||||
newBet.IsShopBet = false
|
||||
err = s.DeductBetFromCustomerWallet(ctx, req.Amount, userID)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("customer wallet deduction failed",
|
||||
zap.Float32("amount", req.Amount),
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Error(err),
|
||||
)
|
||||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
// err = s.DeductBetFromCustomerWallet(ctx, req.Amount, userID)
|
||||
// if err != nil {
|
||||
// s.mongoLogger.Error("customer wallet deduction failed",
|
||||
// zap.Float32("amount", req.Amount),
|
||||
// zap.Int64("user_id", userID),
|
||||
// zap.Error(err),
|
||||
// )
|
||||
// return domain.CreateBetRes{}, err
|
||||
// }
|
||||
default:
|
||||
s.mongoLogger.Error("unknown role type",
|
||||
zap.String("role", string(role)),
|
||||
|
|
@ -398,6 +398,23 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
|
|||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
// flag bets that have more than three outcomes
|
||||
if len(outcomes) > 3 {
|
||||
flag := domain.CreateFlagReq{
|
||||
BetID: bet.ID,
|
||||
OddID: 0,
|
||||
Reason: fmt.Sprintf("too many outcomes - (%d)", len(outcomes)),
|
||||
}
|
||||
|
||||
_, err := s.betStore.CreateFlag(ctx, flag)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to create flag for bet",
|
||||
zap.Int64("bet_id", bet.ID),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
res := domain.ConvertCreateBet(bet, rows)
|
||||
|
||||
return res, nil
|
||||
|
|
@ -716,7 +733,7 @@ func (s *Service) PlaceRandomBet(ctx context.Context, userID, branchID int64, le
|
|||
return domain.CreateBetRes{}, err
|
||||
}
|
||||
|
||||
count, err := s.GetBetCount(ctx, userID, outcomesHash)
|
||||
count, err := s.GetBetCountByUserID(ctx, userID, outcomesHash)
|
||||
if err != nil {
|
||||
s.mongoLogger.Error("failed to get bet count",
|
||||
zap.Int64("user_id", userID),
|
||||
|
|
@ -799,8 +816,8 @@ func (s *Service) GetBetByFastCode(ctx context.Context, fastcode string) (domain
|
|||
return s.betStore.GetBetByFastCode(ctx, fastcode)
|
||||
}
|
||||
|
||||
func (s *Service) GetBetCount(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||
return s.betStore.GetBetCount(ctx, UserID, outcomesHash)
|
||||
func (s *Service) GetBetCountByUserID(ctx context.Context, UserID int64, outcomesHash string) (int64, error) {
|
||||
return s.betStore.GetBetCountByUserID(ctx, UserID, outcomesHash)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) error {
|
||||
|
|
|
|||
16
reports/report_5min_2025-07-14_18-11.csv
Normal file
16
reports/report_5min_2025-07-14_18-11.csv
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Sports Betting Reports (Periodic)
|
||||
Period,Total Bets,Total Cash Made,Total Cash Out,Total Cash Backs,Total Deposits,Total Withdrawals,Total Tickets
|
||||
5min,0,0.00,0.00,0.00,0.00,0.00,0
|
||||
|
||||
Virtual Game Reports (Periodic)
|
||||
Game Name,Number of Bets,Total Transaction Sum
|
||||
|
||||
Company Reports (Periodic)
|
||||
Company ID,Company Name,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Branch Reports (Periodic)
|
||||
Branch ID,Branch Name,Company ID,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Total Summary
|
||||
Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
0,0.00,0.00,0.00
|
||||
|
16
reports/report_5min_2025-07-14_18-15.csv
Normal file
16
reports/report_5min_2025-07-14_18-15.csv
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Sports Betting Reports (Periodic)
|
||||
Period,Total Bets,Total Cash Made,Total Cash Out,Total Cash Backs,Total Deposits,Total Withdrawals,Total Tickets
|
||||
5min,0,0.00,0.00,0.00,0.00,0.00,0
|
||||
|
||||
Virtual Game Reports (Periodic)
|
||||
Game Name,Number of Bets,Total Transaction Sum
|
||||
|
||||
Company Reports (Periodic)
|
||||
Company ID,Company Name,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Branch Reports (Periodic)
|
||||
Branch ID,Branch Name,Company ID,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Total Summary
|
||||
Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
0,0.00,0.00,0.00
|
||||
|
16
reports/report_5min_2025-07-14_18-16.csv
Normal file
16
reports/report_5min_2025-07-14_18-16.csv
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Sports Betting Reports (Periodic)
|
||||
Period,Total Bets,Total Cash Made,Total Cash Out,Total Cash Backs,Total Deposits,Total Withdrawals,Total Tickets
|
||||
5min,0,0.00,0.00,0.00,0.00,0.00,0
|
||||
|
||||
Virtual Game Reports (Periodic)
|
||||
Game Name,Number of Bets,Total Transaction Sum
|
||||
|
||||
Company Reports (Periodic)
|
||||
Company ID,Company Name,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Branch Reports (Periodic)
|
||||
Branch ID,Branch Name,Company ID,Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
|
||||
Total Summary
|
||||
Total Bets,Total Cash In,Total Cash Out,Total Cash Backs
|
||||
0,0.00,0.00,0.00
|
||||
|
Loading…
Reference in New Issue
Block a user