feat: custom odd and disabling odds
This commit is contained in:
parent
437780f3e9
commit
6347984102
|
|
@ -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
26
db/query/custom_odds.sql
Normal 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;
|
||||
25
db/query/disabled_odds.sql
Normal file
25
db/query/disabled_odds.sql
Normal 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;
|
||||
|
|
@ -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
139
gen/db/custom_odds.sql.go
Normal 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
128
gen/db/disabled_odds.sql.go
Normal 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
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
43
internal/domain/custom_odds.go
Normal file
43
internal/domain/custom_odds.go
Normal 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,
|
||||
}
|
||||
}
|
||||
47
internal/domain/disabled_odds.go
Normal file
47
internal/domain/disabled_odds.go
Normal 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
|
||||
}
|
||||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
184
internal/domain/validtypes.go
Normal file
184
internal/domain/validtypes.go
Normal 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))
|
||||
}
|
||||
5
internal/repository/custom_odds.go
Normal file
5
internal/repository/custom_odds.go
Normal 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.)
|
||||
68
internal/repository/disabled_odds.go
Normal file
68
internal/repository/disabled_odds.go
Normal 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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ---
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user