feat: custom odd and disabling odds

This commit is contained in:
Samuel Tariku 2025-08-19 17:15:31 +03:00
parent 437780f3e9
commit 6347984102
22 changed files with 730 additions and 288 deletions

View File

@ -322,7 +322,6 @@ CREATE TABLE custom_odd (
id BIGSERIAL PRIMARY KEY,
odd_id BIGINT NOT NULL,
raw_odd_id BIGINT NOT NULL,
market_id TEXT NOT NULL,
event_id TEXT NOT NULL,
odd_value DOUBLE PRECISION NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
@ -331,7 +330,6 @@ CREATE TABLE disabled_odd (
id BIGSERIAL PRIMARY KEY,
odd_id BIGINT NOT NULL,
raw_odd_id BIGINT NOT NULL,
market_id TEXT NOT NULL,
event_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

26
db/query/custom_odds.sql Normal file
View File

@ -0,0 +1,26 @@
-- name: InsertCustomOdd :one
INSERT INTO custom_odd (
odd_id,
raw_odd_id,
event_id,
odd_value
)
VALUES ($1, $2, $3, $4)
RETURNING *;
-- name: GetAllCustomOdds :many
SELECT *
FROM custom_odd;
-- name: GetCustomOddByRawOddID :one
SELECT *
FROM custom_odd
WHERE raw_odd_id = $1;
-- name: GetCustomOddByID :one
SELECT *
FROM custom_odd
WHERE id = $1;
-- name: DeleteCustomOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: DeleteCustomOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;

View File

@ -0,0 +1,25 @@
-- name: InsertDisabledOdds :one
INSERT INTO disabled_odd (
odd_id,
event_id,
raw_odd_id
)
VALUES ($1, $2, $3)
RETURNING *;
-- name: GetAllDisabledOdds :many
SELECT *
FROM disabled_odd;
-- name: GetDisabledOddByRawOddID :one
SELECT *
FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: GetDisabledOddByID :one
SELECT *
FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: DeleteDisabledOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;
-- name: DeleteDisabledOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1;

View File

@ -35,9 +35,8 @@ WHERE (
created_at < sqlc.narg('created_after')
OR sqlc.narg('created_after') IS NULL
);
-- name: GetInitialOddPerDay :many
SELECT DISTINCT ON (DATE_TRUNC('day', created_at)) *
SELECT DISTINCT ON (DATE_TRUNC($1, created_at)) *
FROM odd_history
WHERE (
odd_id = sqlc.narg('odd_id')
@ -63,5 +62,5 @@ WHERE (
created_at < sqlc.narg('created_after')
OR sqlc.narg('created_after') IS NULL
)
ORDER BY DATE_TRUNC('day', created_at),
ORDER BY DATE_TRUNC($1, created_at),
created_at ASC;

139
gen/db/custom_odds.sql.go Normal file
View File

@ -0,0 +1,139 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: custom_odds.sql
package dbgen
import (
"context"
)
const DeleteCustomOddsByID = `-- name: DeleteCustomOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteCustomOddsByID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteCustomOddsByID, rawOddID)
return err
}
const DeleteCustomOddsByRawOddID = `-- name: DeleteCustomOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteCustomOddsByRawOddID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteCustomOddsByRawOddID, rawOddID)
return err
}
const GetAllCustomOdds = `-- name: GetAllCustomOdds :many
SELECT id, odd_id, raw_odd_id, event_id, odd_value, created_at
FROM custom_odd
`
func (q *Queries) GetAllCustomOdds(ctx context.Context) ([]CustomOdd, error) {
rows, err := q.db.Query(ctx, GetAllCustomOdds)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CustomOdd
for rows.Next() {
var i CustomOdd
if err := rows.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.OddValue,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetCustomOddByID = `-- name: GetCustomOddByID :one
SELECT id, odd_id, raw_odd_id, event_id, odd_value, created_at
FROM custom_odd
WHERE id = $1
`
func (q *Queries) GetCustomOddByID(ctx context.Context, id int64) (CustomOdd, error) {
row := q.db.QueryRow(ctx, GetCustomOddByID, id)
var i CustomOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.OddValue,
&i.CreatedAt,
)
return i, err
}
const GetCustomOddByRawOddID = `-- name: GetCustomOddByRawOddID :one
SELECT id, odd_id, raw_odd_id, event_id, odd_value, created_at
FROM custom_odd
WHERE raw_odd_id = $1
`
func (q *Queries) GetCustomOddByRawOddID(ctx context.Context, rawOddID int64) (CustomOdd, error) {
row := q.db.QueryRow(ctx, GetCustomOddByRawOddID, rawOddID)
var i CustomOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.OddValue,
&i.CreatedAt,
)
return i, err
}
const InsertCustomOdd = `-- name: InsertCustomOdd :one
INSERT INTO custom_odd (
odd_id,
raw_odd_id,
event_id,
odd_value
)
VALUES ($1, $2, $3, $4)
RETURNING id, odd_id, raw_odd_id, event_id, odd_value, created_at
`
type InsertCustomOddParams struct {
OddID int64 `json:"odd_id"`
RawOddID int64 `json:"raw_odd_id"`
EventID string `json:"event_id"`
OddValue float64 `json:"odd_value"`
}
func (q *Queries) InsertCustomOdd(ctx context.Context, arg InsertCustomOddParams) (CustomOdd, error) {
row := q.db.QueryRow(ctx, InsertCustomOdd,
arg.OddID,
arg.RawOddID,
arg.EventID,
arg.OddValue,
)
var i CustomOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.OddValue,
&i.CreatedAt,
)
return i, err
}

128
gen/db/disabled_odds.sql.go Normal file
View File

@ -0,0 +1,128 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: disabled_odds.sql
package dbgen
import (
"context"
)
const DeleteDisabledOddsByID = `-- name: DeleteDisabledOddsByID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteDisabledOddsByID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteDisabledOddsByID, rawOddID)
return err
}
const DeleteDisabledOddsByRawOddID = `-- name: DeleteDisabledOddsByRawOddID :exec
DELETE FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) DeleteDisabledOddsByRawOddID(ctx context.Context, rawOddID int64) error {
_, err := q.db.Exec(ctx, DeleteDisabledOddsByRawOddID, rawOddID)
return err
}
const GetAllDisabledOdds = `-- name: GetAllDisabledOdds :many
SELECT id, odd_id, raw_odd_id, event_id, created_at
FROM disabled_odd
`
func (q *Queries) GetAllDisabledOdds(ctx context.Context) ([]DisabledOdd, error) {
rows, err := q.db.Query(ctx, GetAllDisabledOdds)
if err != nil {
return nil, err
}
defer rows.Close()
var items []DisabledOdd
for rows.Next() {
var i DisabledOdd
if err := rows.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const GetDisabledOddByID = `-- name: GetDisabledOddByID :one
SELECT id, odd_id, raw_odd_id, event_id, created_at
FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) GetDisabledOddByID(ctx context.Context, rawOddID int64) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, GetDisabledOddByID, rawOddID)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}
const GetDisabledOddByRawOddID = `-- name: GetDisabledOddByRawOddID :one
SELECT id, odd_id, raw_odd_id, event_id, created_at
FROM disabled_odd
WHERE raw_odd_id = $1
`
func (q *Queries) GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, GetDisabledOddByRawOddID, rawOddID)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}
const InsertDisabledOdds = `-- name: InsertDisabledOdds :one
INSERT INTO disabled_odd (
odd_id,
event_id,
raw_odd_id
)
VALUES ($1, $2, $3)
RETURNING id, odd_id, raw_odd_id, event_id, created_at
`
type InsertDisabledOddsParams struct {
OddID int64 `json:"odd_id"`
EventID string `json:"event_id"`
RawOddID int64 `json:"raw_odd_id"`
}
func (q *Queries) InsertDisabledOdds(ctx context.Context, arg InsertDisabledOddsParams) (DisabledOdd, error) {
row := q.db.QueryRow(ctx, InsertDisabledOdds, arg.OddID, arg.EventID, arg.RawOddID)
var i DisabledOdd
err := row.Scan(
&i.ID,
&i.OddID,
&i.RawOddID,
&i.EventID,
&i.CreatedAt,
)
return i, err
}

View File

@ -212,7 +212,6 @@ type CustomOdd struct {
ID int64 `json:"id"`
OddID int64 `json:"odd_id"`
RawOddID int64 `json:"raw_odd_id"`
MarketID string `json:"market_id"`
EventID string `json:"event_id"`
OddValue float64 `json:"odd_value"`
CreatedAt pgtype.Timestamp `json:"created_at"`
@ -262,7 +261,6 @@ type DisabledOdd struct {
ID int64 `json:"id"`
OddID int64 `json:"odd_id"`
RawOddID int64 `json:"raw_odd_id"`
MarketID string `json:"market_id"`
EventID string `json:"event_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@ -85,37 +85,38 @@ func (q *Queries) GetAllOddHistory(ctx context.Context, arg GetAllOddHistoryPara
}
const GetInitialOddPerDay = `-- name: GetInitialOddPerDay :many
SELECT DISTINCT ON (DATE_TRUNC('day', created_at)) id, odd_id, raw_odd_id, market_id, event_id, odd_value, created_at
SELECT DISTINCT ON (DATE_TRUNC($1, created_at)) id, odd_id, raw_odd_id, market_id, event_id, odd_value, created_at
FROM odd_history
WHERE (
odd_id = $1
OR $1 IS NULL
)
AND (
market_id = $2
odd_id = $2
OR $2 IS NULL
)
AND (
raw_odd_id = $3
market_id = $3
OR $3 IS NULL
)
AND (
event_id = $4
raw_odd_id = $4
OR $4 IS NULL
)
AND (
created_at > $5
event_id = $5
OR $5 IS NULL
)
AND (
created_at < $6
created_at > $6
OR $6 IS NULL
)
ORDER BY DATE_TRUNC('day', created_at),
AND (
created_at < $7
OR $7 IS NULL
)
ORDER BY DATE_TRUNC($1, created_at),
created_at ASC
`
type GetInitialOddPerDayParams struct {
DateTrunc string `json:"date_trunc"`
OddID pgtype.Int8 `json:"odd_id"`
MarketID pgtype.Text `json:"market_id"`
RawOddID pgtype.Int8 `json:"raw_odd_id"`
@ -126,6 +127,7 @@ type GetInitialOddPerDayParams struct {
func (q *Queries) GetInitialOddPerDay(ctx context.Context, arg GetInitialOddPerDayParams) ([]OddHistory, error) {
rows, err := q.db.Query(ctx, GetInitialOddPerDay,
arg.DateTrunc,
arg.OddID,
arg.MarketID,
arg.RawOddID,

View File

@ -4,6 +4,9 @@ import (
"time"
)
// The Odd ID here is not the odd id from our database
// but the raw_odd_id from the betapi.from within the raw_odds json
// This can be refactor later
type BetOutcome struct {
ID int64 `json:"id" example:"1"`
BetID int64 `json:"bet_id" example:"1"`

View File

@ -1,188 +1,11 @@
package domain
import (
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/jackc/pgx/v5/pgtype"
"go.uber.org/zap"
)
var MongoDBLogger *zap.Logger
type ValidInt64 struct {
Value int64
Valid bool
}
type ValidInt struct {
Value int
Valid bool
}
type ValidInt32 struct {
Value int32
Valid bool
}
type ValidFloat32 struct {
Value float32
Valid bool
}
type ValidString struct {
Value string
Valid bool
}
type ValidTime struct {
Value time.Time
Valid bool
}
type ValidBool struct {
Value bool
Valid bool
}
// ValidInt64 → pgtype.Int8
func (v ValidInt64) ToPG() pgtype.Int8 {
return pgtype.Int8{
Int64: v.Value,
Valid: v.Valid,
}
}
// ValidInt32 → pgtype.Int4
func (v ValidInt32) ToPG() pgtype.Int4 {
return pgtype.Int4{
Int32: v.Value,
Valid: v.Valid,
}
}
// ValidInt → pgtype.Int4 (Go int mapped to int32 for pg compatibility)
func (v ValidInt) ToPG() pgtype.Int4 {
return pgtype.Int4{
Int32: int32(v.Value),
Valid: v.Valid,
}
}
// ValidFloat32 → pgtype.Float4
func (v ValidFloat32) ToPG() pgtype.Float4 {
return pgtype.Float4{
Float32: v.Value,
Valid: v.Valid,
}
}
// ValidString → pgtype.Text
func (v ValidString) ToPG() pgtype.Text {
return pgtype.Text{
String: v.Value,
Valid: v.Valid,
}
}
// ValidTime → pgtype.Timestamp
func (v ValidTime) ToPG() pgtype.Timestamp {
return pgtype.Timestamp{
Time: v.Value,
Valid: v.Valid,
}
}
// ValidBool → pgtype.Bool
func (v ValidBool) ToPG() pgtype.Bool {
return pgtype.Bool{
Bool: v.Value,
Valid: v.Valid,
}
}
func ConvertInt64Ptr(value *int64) ValidInt64 {
if value == nil {
return ValidInt64{}
}
return ValidInt64{
Value: *value,
Valid: true,
}
}
func ConvertInt32Ptr(value *int32) ValidInt32 {
if value == nil {
return ValidInt32{}
}
return ValidInt32{
Value: *value,
Valid: true,
}
}
func ConvertStringPtr(value *string) ValidString {
if value == nil {
return ValidString{}
}
return ValidString{
Value: *value,
Valid: true,
}
}
func ConvertFloat32Ptr(value *float32) ValidFloat32 {
if value == nil {
return ValidFloat32{}
}
return ValidFloat32{
Value: *value,
Valid: true,
}
}
func ConvertCurrencyFloatPtr(value *float32) ValidInt64 {
if value == nil {
return ValidInt64{}
}
convertedCurrency := ToCurrency(*value)
return ValidInt64{
Value: int64(convertedCurrency),
Valid: true,
}
}
func ConvertBoolPtr(value *bool) ValidBool {
if value == nil {
return ValidBool{}
}
return ValidBool{
Value: *value,
Valid: true,
}
}
type Currency int64
// ToCurrency converts a float32 to Currency
func ToCurrency(f float32) Currency {
return Currency((f * 100) + 0.5)
}
// Float32 converts a Currency to float32
func (m Currency) Float32() float32 {
x := float32(m)
x = x / 100
return x
}
// String returns a formatted Currency value
func (m Currency) String() string {
x := float32(m)
x = x / 100
return fmt.Sprintf("$%.2f", x)
}
type ResponseWDataFactory[T any] struct {
Data T `json:"data"`
Response
@ -215,71 +38,3 @@ type Pagination struct {
func PtrFloat64(v float64) *float64 { return &v }
func PtrInt64(v int64) *int64 { return &v }
type Int64JSON int64
// func (i *Int64JSON) Parse() (int64, error) {
// var asString string
// if err := json.Unmarshal(i, &asString); err == nil {
// // Try to parse the string to int64
// return strconv.ParseInt(strings.TrimSpace(asString), 10, 64)
// }
// var asInt int64
// if err := json.Unmarshal(i, &asInt); err == nil {
// return asInt, nil
// }
// // Neither string nor int worked
// return 0, fmt.Errorf("invalid int64 value: %s", string(i))
// }
func (i *Int64JSON) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err == nil {
// it was a string, parse it
v, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
*i = Int64JSON(v)
return nil
}
var v int64
if err := json.Unmarshal(data, &v); err == nil {
*i = Int64JSON(v)
return nil
}
return fmt.Errorf("invalid int64 value: %s", string(data))
}
type NullableInt64JSON struct {
Int64 int64
Valid bool
}
func (n *NullableInt64JSON) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err == nil {
if s == "" {
n.Valid = false
return nil
}
v, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
n.Int64, n.Valid = v, true
return nil
}
var v int64
if err := json.Unmarshal(data, &v); err == nil {
n.Int64, n.Valid = v, true
return nil
}
return fmt.Errorf("invalid int64 value: %s", string(data))
}

View File

@ -6,6 +6,27 @@ import (
"time"
)
type Currency int64
// ToCurrency converts a float32 to Currency
func ToCurrency(f float32) Currency {
return Currency((f * 100) + 0.5)
}
// Float32 converts a Currency to float32
func (m Currency) Float32() float32 {
x := float32(m)
x = x / 100
return x
}
// String returns a formatted Currency value
func (m Currency) String() string {
x := float32(m)
x = x / 100
return fmt.Sprintf("$%.2f", x)
}
type IntCurrency string
const (

View File

@ -0,0 +1,43 @@
package domain
import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type CustomOdd struct {
ID int64
OddID int64
RawOddID int64
EventID string
OddValue float64
CreatedAt time.Time
}
type CreateCustomOdd struct {
OddID int64
RawOddID int64
EventID string
OddValue float64
}
func ConvertCreateCustomOdd(odd CreateCustomOdd) dbgen.InsertCustomOddParams {
return dbgen.InsertCustomOddParams{
OddID: odd.OddID,
RawOddID: odd.RawOddID,
EventID: odd.EventID,
OddValue: odd.OddValue,
}
}
func ConvertDBCustomOdd(dbCustomOdd dbgen.CustomOdd) CustomOdd {
return CustomOdd{
ID: dbCustomOdd.ID,
OddID: dbCustomOdd.OddID,
RawOddID: dbCustomOdd.RawOddID,
EventID: dbCustomOdd.EventID,
OddValue: dbCustomOdd.OddValue,
CreatedAt: dbCustomOdd.CreatedAt.Time,
}
}

View File

@ -0,0 +1,47 @@
package domain
import (
"time"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
)
type DisabledOdd struct {
ID int64
OddID int64
RawOddID int64
EventID string
CreatedAt time.Time
}
type CreateDisabledOdd struct {
OddID int64
RawOddID int64
EventID string
}
func ConvertCreateDisabledOdd(odd CreateDisabledOdd) dbgen.InsertDisabledOddsParams {
return dbgen.InsertDisabledOddsParams{
OddID: odd.OddID,
EventID: odd.EventID,
RawOddID: odd.RawOddID,
}
}
func ConvertDBDisabledOdd(dbDisabledOdd dbgen.DisabledOdd) DisabledOdd {
return DisabledOdd{
ID: dbDisabledOdd.ID,
OddID: dbDisabledOdd.OddID,
RawOddID: dbDisabledOdd.RawOddID,
EventID: dbDisabledOdd.EventID,
CreatedAt: dbDisabledOdd.CreatedAt.Time,
}
}
func ConvertDisabledOdds(list []dbgen.DisabledOdd) []DisabledOdd {
result := make([]DisabledOdd, 0, len(list))
for _, item := range list {
result = append(result, ConvertDBDisabledOdd(item))
}
return result
}

View File

@ -27,7 +27,7 @@ type RawOdd struct {
// The Market ID for the json data can be either string / int which is causing problems when UnMarshalling
type OddsMarket struct {
ID NullableInt64JSON `json:"id"`
ID ValidInt64 `json:"id"`
Name string `json:"name"`
Odds []json.RawMessage `json:"odds"`
Header string `json:"header,omitempty"`

View File

@ -54,3 +54,11 @@ func ConvertDBOddHistory(dbOddHistory dbgen.OddHistory) OddHistory {
CreatedAt: dbOddHistory.CreatedAt.Time,
}
}
func ConvertOddHistories(list []dbgen.OddHistory) []OddHistory {
result := make([]OddHistory, 0, len(list))
for _, item := range list {
result = append(result, ConvertDBOddHistory(item))
}
return result
}

View File

@ -16,10 +16,10 @@ type LeagueRes struct {
}
type Team struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID NullableInt64JSON `json:"image_id"`
CC string `json:"cc"`
ID string `json:"id"`
Name string `json:"name"`
ImageID ValidInt64 `json:"image_id"`
CC string `json:"cc"`
}
type Score struct {
@ -28,14 +28,14 @@ type Score struct {
}
type CommonResultResponse struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
TimeStatus NullableInt64JSON `json:"time_status"`
League LeagueRes `json:"league"`
Home Team `json:"home"`
Away Team `json:"away"`
SS string `json:"ss"`
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
TimeStatus ValidInt64 `json:"time_status"`
League LeagueRes `json:"league"`
Home Team `json:"home"`
Away Team `json:"away"`
SS string `json:"ss"`
}
type FootballResultResponse struct {

View File

@ -0,0 +1,184 @@
package domain
import (
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/jackc/pgx/v5/pgtype"
)
type ValidInt64 struct {
Value int64
Valid bool
}
type ValidInt struct {
Value int
Valid bool
}
type ValidInt32 struct {
Value int32
Valid bool
}
type ValidFloat32 struct {
Value float32
Valid bool
}
type ValidString struct {
Value string
Valid bool
}
type ValidTime struct {
Value time.Time
Valid bool
}
type ValidBool struct {
Value bool
Valid bool
}
// ValidInt64 → pgtype.Int8
func (v ValidInt64) ToPG() pgtype.Int8 {
return pgtype.Int8{
Int64: v.Value,
Valid: v.Valid,
}
}
// ValidInt32 → pgtype.Int4
func (v ValidInt32) ToPG() pgtype.Int4 {
return pgtype.Int4{
Int32: v.Value,
Valid: v.Valid,
}
}
// ValidInt → pgtype.Int4 (Go int mapped to int32 for pg compatibility)
func (v ValidInt) ToPG() pgtype.Int4 {
return pgtype.Int4{
Int32: int32(v.Value),
Valid: v.Valid,
}
}
// ValidFloat32 → pgtype.Float4
func (v ValidFloat32) ToPG() pgtype.Float4 {
return pgtype.Float4{
Float32: v.Value,
Valid: v.Valid,
}
}
// ValidString → pgtype.Text
func (v ValidString) ToPG() pgtype.Text {
return pgtype.Text{
String: v.Value,
Valid: v.Valid,
}
}
// ValidTime → pgtype.Timestamp
func (v ValidTime) ToPG() pgtype.Timestamp {
return pgtype.Timestamp{
Time: v.Value,
Valid: v.Valid,
}
}
// ValidBool → pgtype.Bool
func (v ValidBool) ToPG() pgtype.Bool {
return pgtype.Bool{
Bool: v.Value,
Valid: v.Valid,
}
}
func ConvertInt64Ptr(value *int64) ValidInt64 {
if value == nil {
return ValidInt64{}
}
return ValidInt64{
Value: *value,
Valid: true,
}
}
func ConvertInt32Ptr(value *int32) ValidInt32 {
if value == nil {
return ValidInt32{}
}
return ValidInt32{
Value: *value,
Valid: true,
}
}
func ConvertStringPtr(value *string) ValidString {
if value == nil {
return ValidString{}
}
return ValidString{
Value: *value,
Valid: true,
}
}
func ConvertFloat32Ptr(value *float32) ValidFloat32 {
if value == nil {
return ValidFloat32{}
}
return ValidFloat32{
Value: *value,
Valid: true,
}
}
func ConvertCurrencyFloatPtr(value *float32) ValidInt64 {
if value == nil {
return ValidInt64{}
}
convertedCurrency := ToCurrency(*value)
return ValidInt64{
Value: int64(convertedCurrency),
Valid: true,
}
}
func ConvertBoolPtr(value *bool) ValidBool {
if value == nil {
return ValidBool{}
}
return ValidBool{
Value: *value,
Valid: true,
}
}
func (n *ValidInt64) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err == nil {
if s == "" {
n.Valid = false
return nil
}
v, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
n.Value, n.Valid = v, true
return nil
}
var v int64
if err := json.Unmarshal(data, &v); err == nil {
n.Value, n.Valid = v, true
return nil
}
return fmt.Errorf("invalid int64 value: %s", string(data))
}

View File

@ -0,0 +1,5 @@
package repository
import "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
func (s *Store) InsertCustomOdds(ctx context.Context, odd domain.ConvertCreateCustomOdd) (domain.)

View File

@ -0,0 +1,68 @@
package repository
import (
"context"
"fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
func (s *Store) InsertDisabledOdd(ctx context.Context, odd domain.CreateDisabledOdd) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.InsertDisabledOdds(ctx, domain.ConvertCreateDisabledOdd(odd))
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("InsertDisabledOdd failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) GetAllDisabledOdds(ctx context.Context) ([]domain.DisabledOdd, error) {
dbDisabledOdds, err := s.queries.GetAllDisabledOdds(ctx)
if err != nil {
return nil, fmt.Errorf("GetAllDisabledOdds failed: %w", err)
}
return domain.ConvertDisabledOdds(dbDisabledOdds), nil
}
func (s *Store) GetDisabledOddByRawOddID(ctx context.Context, rawOddID int64) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.GetDisabledOddByRawOddID(ctx, rawOddID)
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("GetDisabledOddByRawOddID failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) GetDisabledOddByID(ctx context.Context, id int64) (domain.DisabledOdd, error) {
dbDisabledOdd, err := s.queries.GetDisabledOddByID(ctx, id)
if err != nil {
return domain.DisabledOdd{}, fmt.Errorf("GetDisabledOddByID failed: %w", err)
}
return domain.ConvertDBDisabledOdd(dbDisabledOdd), nil
}
func (s *Store) DeleteDisabledOddsByID(ctx context.Context, id int64) error {
err := s.queries.DeleteDisabledOddsByID(ctx, id)
if err != nil {
return fmt.Errorf("DeleteDisabledOddsByID failed: %w", err)
}
return nil
}
func (s *Store) DeleteDisabledOddsByRawOddID(ctx context.Context, id int64) error {
err := s.queries.DeleteDisabledOddsByRawOddID(ctx, id)
if err != nil {
return fmt.Errorf("DeleteDisabledOddsByRawOddID failed: %w", err)
}
return nil
}

View File

@ -18,14 +18,6 @@ func (s *Store) InsertOddHistory(ctx context.Context, odd domain.CreateOddHistor
return domain.ConvertDBOddHistory(dbOddHistory), nil
}
func convertOddHistories(list []dbgen.OddHistory) []domain.OddHistory {
result := make([]domain.OddHistory, 0, len(list))
for _, item := range list {
result = append(result, domain.ConvertDBOddHistory(item))
}
return result
}
func (s *Store) GetAllOddHistory(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error) {
dbOddHistories, err := s.queries.GetAllOddHistory(ctx, dbgen.GetAllOddHistoryParams{
OddID: filter.OddID.ToPG(),
@ -40,7 +32,7 @@ func (s *Store) GetAllOddHistory(ctx context.Context, filter domain.OddHistoryFi
return nil, fmt.Errorf("GetAllOddHistory failed: %w", err)
}
return convertOddHistories(dbOddHistories), nil
return domain.ConvertOddHistories(dbOddHistories), nil
}
func (s *Store) GetInitialOddPerDay(ctx context.Context, filter domain.OddHistoryFilter) ([]domain.OddHistory, error) {
@ -51,10 +43,11 @@ func (s *Store) GetInitialOddPerDay(ctx context.Context, filter domain.OddHistor
EventID: filter.EventID.ToPG(),
CreatedAfter: filter.CreatedAfter.ToPG(),
CreatedBefore: filter.CreatedBefore.ToPG(),
DateTrunc: "day",
})
if err != nil {
return nil, fmt.Errorf("GetInitialOddPerDay failed: %w", err)
}
return convertOddHistories(dbOddHistories), nil
return domain.ConvertOddHistories(dbOddHistories), nil
}

View File

@ -259,7 +259,7 @@ func (s *service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
// --- 1. Validate PlayerID ---
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
z`` return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
}
// --- 2. Get player wallets ---