small fixes and getting it ready for deployment
This commit is contained in:
parent
9e4b0d9942
commit
98e30b5051
|
|
@ -161,6 +161,7 @@ CREATE TABLE IF NOT EXISTS transactions (
|
|||
account_number VARCHAR(255) NOT NULL,
|
||||
reference_number VARCHAR(255) NOT NULL,
|
||||
verified BOOLEAN NOT NULL DEFAULT false,
|
||||
approved_by BIGINT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
|
@ -243,7 +244,6 @@ CREATE TABLE odds (
|
|||
UNIQUE (event_id, market_id, name, handicap),
|
||||
UNIQUE (event_id, market_id)
|
||||
);
|
||||
|
||||
CREATE TABLE companies (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
|
|
@ -397,4 +397,4 @@ VALUES (
|
|||
TRUE,
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
);
|
||||
);
|
||||
|
|
@ -1,16 +1,51 @@
|
|||
-- name: CreateTransaction :one
|
||||
INSERT INTO transactions (amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING *;
|
||||
|
||||
INSERT INTO transactions (
|
||||
amount,
|
||||
branch_id,
|
||||
cashier_id,
|
||||
bet_id,
|
||||
type,
|
||||
payment_option,
|
||||
full_name,
|
||||
phone_number,
|
||||
bank_code,
|
||||
beneficiary_name,
|
||||
account_name,
|
||||
account_number,
|
||||
reference_number,
|
||||
number_of_outcomes
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13,
|
||||
$14
|
||||
)
|
||||
RETURNING *;
|
||||
-- name: GetAllTransactions :many
|
||||
SELECT * FROM transactions;
|
||||
|
||||
SELECT *
|
||||
FROM transactions;
|
||||
-- name: GetTransactionByID :one
|
||||
SELECT * FROM transactions WHERE id = $1;
|
||||
|
||||
SELECT *
|
||||
FROM transactions
|
||||
WHERE id = $1;
|
||||
-- name: GetTransactionByBranch :many
|
||||
SELECT * FROM transactions WHERE branch_id = $1;
|
||||
|
||||
SELECT *
|
||||
FROM transactions
|
||||
WHERE branch_id = $1;
|
||||
-- name: UpdateTransactionVerified :exec
|
||||
UPDATE transactions SET verified = $2, updated_at = CURRENT_TIMESTAMP WHERE id = $1;
|
||||
|
||||
|
||||
UPDATE transactions
|
||||
SET verified = $2,
|
||||
approved_by = $3,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1;
|
||||
105
docs/docs.go
105
docs/docs.go
|
|
@ -55,7 +55,7 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
"$ref": "#/definitions/handlers.AdminRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -1449,7 +1449,7 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
"$ref": "#/definitions/handlers.ManagersRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -3445,7 +3445,7 @@ const docTemplate = `{
|
|||
"OUTCOME_STATUS_PENDING",
|
||||
"OUTCOME_STATUS_WIN",
|
||||
"OUTCOME_STATUS_LOSS",
|
||||
"OUTCOME_STATUS_ERROR"
|
||||
"OUTCOME_STATUS_VOID"
|
||||
]
|
||||
},
|
||||
"domain.PaymentOption": {
|
||||
|
|
@ -3703,6 +3703,50 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.AdminRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"role": {
|
||||
"$ref": "#/definitions/domain.Role"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"suspended_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.BetRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -3851,9 +3895,6 @@ const docTemplate = `{
|
|||
},
|
||||
"handlers.CheckPhoneEmailExistReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone_number"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -3971,10 +4012,6 @@ const docTemplate = `{
|
|||
}
|
||||
],
|
||||
"example": 1
|
||||
},
|
||||
"total_odds": {
|
||||
"type": "number",
|
||||
"example": 4.22
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4140,10 +4177,6 @@ const docTemplate = `{
|
|||
"items": {
|
||||
"$ref": "#/definitions/handlers.CreateTicketOutcomeReq"
|
||||
}
|
||||
},
|
||||
"total_odds": {
|
||||
"type": "number",
|
||||
"example": 4.22
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4267,6 +4300,50 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.ManagersRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"role": {
|
||||
"$ref": "#/definitions/domain.Role"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"suspended_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.RegisterCodeReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
"$ref": "#/definitions/handlers.AdminRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -1441,7 +1441,7 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.APIResponse"
|
||||
"$ref": "#/definitions/handlers.ManagersRes"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
|
|
@ -3437,7 +3437,7 @@
|
|||
"OUTCOME_STATUS_PENDING",
|
||||
"OUTCOME_STATUS_WIN",
|
||||
"OUTCOME_STATUS_LOSS",
|
||||
"OUTCOME_STATUS_ERROR"
|
||||
"OUTCOME_STATUS_VOID"
|
||||
]
|
||||
},
|
||||
"domain.PaymentOption": {
|
||||
|
|
@ -3695,6 +3695,50 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.AdminRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"role": {
|
||||
"$ref": "#/definitions/domain.Role"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"suspended_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.BetRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -3843,9 +3887,6 @@
|
|||
},
|
||||
"handlers.CheckPhoneEmailExistReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone_number"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
|
|
@ -3963,10 +4004,6 @@
|
|||
}
|
||||
],
|
||||
"example": 1
|
||||
},
|
||||
"total_odds": {
|
||||
"type": "number",
|
||||
"example": 4.22
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4132,10 +4169,6 @@
|
|||
"items": {
|
||||
"$ref": "#/definitions/handlers.CreateTicketOutcomeReq"
|
||||
}
|
||||
},
|
||||
"total_odds": {
|
||||
"type": "number",
|
||||
"example": 4.22
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4259,6 +4292,50 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"handlers.ManagersRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"email_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"first_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"last_login": {
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_number": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone_verified": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"role": {
|
||||
"$ref": "#/definitions/domain.Role"
|
||||
},
|
||||
"suspended": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"suspended_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handlers.RegisterCodeReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ definitions:
|
|||
- OUTCOME_STATUS_PENDING
|
||||
- OUTCOME_STATUS_WIN
|
||||
- OUTCOME_STATUS_LOSS
|
||||
- OUTCOME_STATUS_ERROR
|
||||
- OUTCOME_STATUS_VOID
|
||||
domain.PaymentOption:
|
||||
enum:
|
||||
- 0
|
||||
|
|
@ -272,6 +272,35 @@ definitions:
|
|||
description: Converted from "time" field in UNIX format
|
||||
type: string
|
||||
type: object
|
||||
handlers.AdminRes:
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
email_verified:
|
||||
type: boolean
|
||||
first_name:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
last_login:
|
||||
type: string
|
||||
last_name:
|
||||
type: string
|
||||
phone_number:
|
||||
type: string
|
||||
phone_verified:
|
||||
type: boolean
|
||||
role:
|
||||
$ref: '#/definitions/domain.Role'
|
||||
suspended:
|
||||
type: boolean
|
||||
suspended_at:
|
||||
type: string
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
handlers.BetRes:
|
||||
properties:
|
||||
amount:
|
||||
|
|
@ -384,8 +413,6 @@ definitions:
|
|||
phone_number:
|
||||
example: "1234567890"
|
||||
type: string
|
||||
required:
|
||||
- phone_number
|
||||
type: object
|
||||
handlers.CheckPhoneEmailExistRes:
|
||||
properties:
|
||||
|
|
@ -461,9 +488,6 @@ definitions:
|
|||
allOf:
|
||||
- $ref: '#/definitions/domain.OutcomeStatus'
|
||||
example: 1
|
||||
total_odds:
|
||||
example: 4.22
|
||||
type: number
|
||||
type: object
|
||||
handlers.CreateBranchOperationReq:
|
||||
properties:
|
||||
|
|
@ -581,9 +605,6 @@ definitions:
|
|||
items:
|
||||
$ref: '#/definitions/handlers.CreateTicketOutcomeReq'
|
||||
type: array
|
||||
total_odds:
|
||||
example: 4.22
|
||||
type: number
|
||||
type: object
|
||||
handlers.CreateTicketRes:
|
||||
properties:
|
||||
|
|
@ -668,6 +689,35 @@ definitions:
|
|||
static_updated_at:
|
||||
type: string
|
||||
type: object
|
||||
handlers.ManagersRes:
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
email_verified:
|
||||
type: boolean
|
||||
first_name:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
last_login:
|
||||
type: string
|
||||
last_name:
|
||||
type: string
|
||||
phone_number:
|
||||
type: string
|
||||
phone_verified:
|
||||
type: boolean
|
||||
role:
|
||||
$ref: '#/definitions/domain.Role'
|
||||
suspended:
|
||||
type: boolean
|
||||
suspended_at:
|
||||
type: string
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
handlers.RegisterCodeReq:
|
||||
properties:
|
||||
email:
|
||||
|
|
@ -1055,7 +1105,7 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
$ref: '#/definitions/handlers.AdminRes'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
|
|
@ -1975,7 +2025,7 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.APIResponse'
|
||||
$ref: '#/definitions/handlers.ManagersRes'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ type Transaction struct {
|
|||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified"`
|
||||
ApprovedBy pgtype.Int8 `json:"approved_by"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updated_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,26 +7,61 @@ package dbgen
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const CreateTransaction = `-- name: CreateTransaction :one
|
||||
INSERT INTO transactions (amount, branch_id, cashier_id, bet_id, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at
|
||||
INSERT INTO transactions (
|
||||
amount,
|
||||
branch_id,
|
||||
cashier_id,
|
||||
bet_id,
|
||||
type,
|
||||
payment_option,
|
||||
full_name,
|
||||
phone_number,
|
||||
bank_code,
|
||||
beneficiary_name,
|
||||
account_name,
|
||||
account_number,
|
||||
reference_number,
|
||||
number_of_outcomes
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13,
|
||||
$14
|
||||
)
|
||||
RETURNING id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateTransactionParams struct {
|
||||
Amount int64 `json:"amount"`
|
||||
BranchID int64 `json:"branch_id"`
|
||||
CashierID int64 `json:"cashier_id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
Type int64 `json:"type"`
|
||||
PaymentOption int64 `json:"payment_option"`
|
||||
FullName string `json:"full_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Amount int64 `json:"amount"`
|
||||
BranchID int64 `json:"branch_id"`
|
||||
CashierID int64 `json:"cashier_id"`
|
||||
BetID int64 `json:"bet_id"`
|
||||
Type int64 `json:"type"`
|
||||
PaymentOption int64 `json:"payment_option"`
|
||||
FullName string `json:"full_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
BankCode string `json:"bank_code"`
|
||||
BeneficiaryName string `json:"beneficiary_name"`
|
||||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
NumberOfOutcomes int64 `json:"number_of_outcomes"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionParams) (Transaction, error) {
|
||||
|
|
@ -44,6 +79,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
|
|||
arg.AccountName,
|
||||
arg.AccountNumber,
|
||||
arg.ReferenceNumber,
|
||||
arg.NumberOfOutcomes,
|
||||
)
|
||||
var i Transaction
|
||||
err := row.Scan(
|
||||
|
|
@ -63,6 +99,7 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
|
|||
&i.AccountNumber,
|
||||
&i.ReferenceNumber,
|
||||
&i.Verified,
|
||||
&i.ApprovedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
|
|
@ -70,7 +107,8 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
|
|||
}
|
||||
|
||||
const GetAllTransactions = `-- name: GetAllTransactions :many
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at
|
||||
FROM transactions
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error) {
|
||||
|
|
@ -99,6 +137,7 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
|
|||
&i.AccountNumber,
|
||||
&i.ReferenceNumber,
|
||||
&i.Verified,
|
||||
&i.ApprovedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
|
|
@ -113,7 +152,9 @@ func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error)
|
|||
}
|
||||
|
||||
const GetTransactionByBranch = `-- name: GetTransactionByBranch :many
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE branch_id = $1
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at
|
||||
FROM transactions
|
||||
WHERE branch_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([]Transaction, error) {
|
||||
|
|
@ -142,6 +183,7 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
|
|||
&i.AccountNumber,
|
||||
&i.ReferenceNumber,
|
||||
&i.Verified,
|
||||
&i.ApprovedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
|
|
@ -156,7 +198,9 @@ func (q *Queries) GetTransactionByBranch(ctx context.Context, branchID int64) ([
|
|||
}
|
||||
|
||||
const GetTransactionByID = `-- name: GetTransactionByID :one
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, created_at, updated_at FROM transactions WHERE id = $1
|
||||
SELECT id, amount, branch_id, cashier_id, bet_id, number_of_outcomes, type, payment_option, full_name, phone_number, bank_code, beneficiary_name, account_name, account_number, reference_number, verified, approved_by, created_at, updated_at
|
||||
FROM transactions
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction, error) {
|
||||
|
|
@ -179,6 +223,7 @@ func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction
|
|||
&i.AccountNumber,
|
||||
&i.ReferenceNumber,
|
||||
&i.Verified,
|
||||
&i.ApprovedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
|
|
@ -186,15 +231,20 @@ func (q *Queries) GetTransactionByID(ctx context.Context, id int64) (Transaction
|
|||
}
|
||||
|
||||
const UpdateTransactionVerified = `-- name: UpdateTransactionVerified :exec
|
||||
UPDATE transactions SET verified = $2, updated_at = CURRENT_TIMESTAMP WHERE id = $1
|
||||
UPDATE transactions
|
||||
SET verified = $2,
|
||||
approved_by = $3,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateTransactionVerifiedParams struct {
|
||||
ID int64 `json:"id"`
|
||||
Verified bool `json:"verified"`
|
||||
ID int64 `json:"id"`
|
||||
Verified bool `json:"verified"`
|
||||
ApprovedBy pgtype.Int8 `json:"approved_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTransactionVerified(ctx context.Context, arg UpdateTransactionVerifiedParams) error {
|
||||
_, err := q.db.Exec(ctx, UpdateTransactionVerified, arg.ID, arg.Verified)
|
||||
_, err := q.db.Exec(ctx, UpdateTransactionVerified, arg.ID, arg.Verified, arg.ApprovedBy)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type TransactionType int
|
||||
|
||||
const (
|
||||
|
|
@ -36,6 +38,9 @@ type Transaction struct {
|
|||
AccountNumber string
|
||||
ReferenceNumber string
|
||||
Verified bool
|
||||
ApprovedBy ValidInt64
|
||||
UpdatedAt time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type CreateTransaction struct {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import (
|
|||
|
||||
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
func convertDBTransaction(transaction dbgen.Transaction) domain.Transaction {
|
||||
return domain.Transaction{
|
||||
ID: transaction.ID,
|
||||
Amount: domain.Currency(transaction.Amount),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
|
|
@ -23,24 +25,32 @@ func convertDBTransaction(transaction dbgen.Transaction) domain.Transaction {
|
|||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
ApprovedBy: domain.ValidInt64{
|
||||
Value: transaction.ApprovedBy.Int64,
|
||||
Valid: transaction.ApprovedBy.Valid,
|
||||
},
|
||||
CreatedAt: transaction.CreatedAt.Time,
|
||||
UpdatedAt: transaction.UpdatedAt.Time,
|
||||
Verified: transaction.Verified,
|
||||
}
|
||||
}
|
||||
|
||||
func convertCreateTransaction(transaction domain.CreateTransaction) dbgen.CreateTransactionParams {
|
||||
return dbgen.CreateTransactionParams{
|
||||
Amount: int64(transaction.Amount),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
Type: int64(transaction.Type),
|
||||
PaymentOption: int64(transaction.PaymentOption),
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
Amount: int64(transaction.Amount),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
Type: int64(transaction.Type),
|
||||
PaymentOption: int64(transaction.PaymentOption),
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
NumberOfOutcomes: transaction.NumberOfOutcomes,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,9 +99,13 @@ func (s *Store) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateTransactionVerified(ctx context.Context, id int64, verified bool) error {
|
||||
func (s *Store) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error {
|
||||
err := s.queries.UpdateTransactionVerified(ctx, dbgen.UpdateTransactionVerifiedParams{
|
||||
ID: id,
|
||||
ID: id,
|
||||
ApprovedBy: pgtype.Int8{
|
||||
Int64: approvedBy,
|
||||
Valid: true,
|
||||
},
|
||||
Verified: verified,
|
||||
})
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ type TransactionStore interface {
|
|||
GetTransactionByID(ctx context.Context, id int64) (domain.Transaction, error)
|
||||
GetAllTransactions(ctx context.Context) ([]domain.Transaction, error)
|
||||
GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error)
|
||||
UpdateTransactionVerified(ctx context.Context, id int64, verified bool) error
|
||||
UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ func (s *Service) GetAllTransactions(ctx context.Context) ([]domain.Transaction,
|
|||
func (s *Service) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error) {
|
||||
return s.transactionStore.GetTransactionByBranch(ctx, id)
|
||||
}
|
||||
func (s *Service) UpdateTransactionVerified(ctx context.Context, id int64, verified bool) error {
|
||||
|
||||
return s.transactionStore.UpdateTransactionVerified(ctx, id, verified)
|
||||
func (s *Service) UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64) error {
|
||||
return s.transactionStore.UpdateTransactionVerified(ctx, id, verified, approvedBy)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
|
|
@ -25,6 +26,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||||
log.Printf("FetchUpcomingEvents error: %v", err)
|
||||
}
|
||||
time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -36,18 +38,17 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
// }
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// // spec: "0 */15 * * * *", // Every 15 minutes
|
||||
// spec: "0 0 * * * *", // TODO: Every hour because of the 3600 requests per hour limit
|
||||
// task: func() {
|
||||
{
|
||||
// spec: "0 */15 * * * *", // Every 15 minutes
|
||||
spec: "0 0 * * * *", // TODO: Every hour because of the 3600 requests per hour limit
|
||||
task: func() {
|
||||
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||
log.Printf("FetchNonLiveOdds error: %v", err)
|
||||
}
|
||||
time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour
|
||||
|
||||
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||
// log.Printf("FetchNonLiveOdds error: %v", err)
|
||||
// }
|
||||
// time.Sleep(2 * time.Second) //This will restrict the fetching to 1800 requests per hour
|
||||
|
||||
// },
|
||||
// },
|
||||
},
|
||||
},
|
||||
// {
|
||||
// spec: "0 */15 * * * *",
|
||||
// task: func() {
|
||||
|
|
@ -71,7 +72,6 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
|
|||
}
|
||||
|
||||
for _, job := range schedule {
|
||||
job.task()
|
||||
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||||
log.Fatalf("Failed to schedule cron job: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ type CreateBetOutcomeReq struct {
|
|||
type CreateBetReq struct {
|
||||
Outcomes []CreateBetOutcomeReq `json:"outcomes"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
||||
Status domain.OutcomeStatus `json:"status" example:"1"`
|
||||
FullName string `json:"full_name" example:"John"`
|
||||
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
||||
BranchID *int64 `json:"branch_id,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
type CreateBetRes struct {
|
||||
|
|
@ -99,6 +99,7 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
|
||||
// Get user_id from middleware
|
||||
userID := c.Locals("user_id").(int64)
|
||||
role := c.Locals("role").(domain.Role)
|
||||
|
||||
var req CreateBetReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
|
|
@ -111,109 +112,13 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
// Validating user by role
|
||||
// Differentiating between offline and online bets
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, user id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
cashoutID, err := h.betSvc.GenerateCashoutID()
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, unable to create cashout id")
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid request", err, nil)
|
||||
}
|
||||
var bet domain.Bet
|
||||
if user.Role == domain.RoleCashier {
|
||||
|
||||
// Get the branch from the branch ID
|
||||
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, branch id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
|
||||
// Deduct a percentage of the amount
|
||||
// TODO move to service layer. Make it fetch dynamically from company
|
||||
var deductedAmount = req.Amount / 10
|
||||
err = h.walletSvc.DeductFromWallet(c.Context(), branch.WalletID, domain.ToCurrency(deductedAmount))
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, unable to deduct from WalletID")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: req.TotalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: branch.ID,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: false,
|
||||
},
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else if user.Role == domain.RoleSuperAdmin {
|
||||
// This is just for testing
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: req.TotalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: 1,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else {
|
||||
// TODO if user is customer, get id from the token then get the wallet id from there and reduce the amount
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: req.TotalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: 0,
|
||||
Valid: false,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: false,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
|
||||
}
|
||||
|
||||
//
|
||||
// TODO Validate Outcomes Here and make sure they didn't expire
|
||||
// Validation for creating tickets
|
||||
if len(req.Outcomes) > 30 {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Too many odds/outcomes selected", nil, nil)
|
||||
}
|
||||
var outcomes []domain.CreateBetOutcome = make([]domain.CreateBetOutcome, 0, len(req.Outcomes))
|
||||
var totalOdds float32 = 1
|
||||
for _, outcome := range req.Outcomes {
|
||||
eventIDStr := strconv.FormatInt(outcome.EventID, 10)
|
||||
marketIDStr := strconv.FormatInt(outcome.MarketID, 10)
|
||||
|
|
@ -262,9 +167,9 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
parsedOdd, err := strconv.ParseFloat(selectedOdd.Odds, 32)
|
||||
totalOdds = totalOdds * float32(parsedOdd)
|
||||
|
||||
outcomes = append(outcomes, domain.CreateBetOutcome{
|
||||
BetID: bet.ID,
|
||||
EventID: outcome.EventID,
|
||||
OddID: outcome.OddID,
|
||||
MarketID: outcome.MarketID,
|
||||
|
|
@ -279,6 +184,108 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|||
})
|
||||
}
|
||||
|
||||
// Validating user by role
|
||||
// Differentiating between offline and online bets
|
||||
cashoutID, err := h.betSvc.GenerateCashoutID()
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, unable to create cashout id")
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid request", err, nil)
|
||||
}
|
||||
var bet domain.Bet
|
||||
if role == domain.RoleCashier {
|
||||
|
||||
// Get the branch from the branch ID
|
||||
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, branch id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
|
||||
// Deduct a percentage of the amount
|
||||
// TODO move to service layer. Make it fetch dynamically from company
|
||||
var deductedAmount = req.Amount / 10
|
||||
err = h.walletSvc.DeductFromWallet(c.Context(), branch.WalletID, domain.ToCurrency(deductedAmount))
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed, unable to deduct from WalletID")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: totalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: branch.ID,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: false,
|
||||
},
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else if role == domain.RoleSuperAdmin || role == domain.RoleAdmin || role == domain.RoleBranchManager {
|
||||
// If a non cashier wants to create a bet, they will need to provide the Branch ID
|
||||
// TODO: restrict the Branch ID of Admin and Branch Manager to only the branches within their own company
|
||||
if req.BranchID == nil {
|
||||
h.logger.Error("CreateBetReq failed, Branch ID is required for this type of user")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID is required for this type of user", nil, nil)
|
||||
}
|
||||
// h.logger.Info("Branch ID", slog.Int64("branch_id", *req.BranchID))
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: totalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: *req.BranchID,
|
||||
Valid: true,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: true,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
} else {
|
||||
// TODO if user is customer, get id from the token then get the wallet id from there and reduce the amount
|
||||
bet, err = h.betSvc.CreateBet(c.Context(), domain.CreateBet{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: totalOdds,
|
||||
Status: req.Status,
|
||||
FullName: req.FullName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
|
||||
BranchID: domain.ValidInt64{
|
||||
Value: 0,
|
||||
Valid: false,
|
||||
},
|
||||
UserID: domain.ValidInt64{
|
||||
Value: userID,
|
||||
Valid: true,
|
||||
},
|
||||
IsShopBet: false,
|
||||
CashoutID: cashoutID,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error("CreateBetReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
|
||||
}
|
||||
|
||||
// Updating the bet id for outcomes
|
||||
for index := range outcomes {
|
||||
outcomes[index].BetID = bet.ID
|
||||
}
|
||||
|
||||
rows, err := h.betSvc.CreateBetOutcome(c.Context(), outcomes)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ type CreateTicketOutcomeReq struct {
|
|||
}
|
||||
|
||||
type CreateTicketReq struct {
|
||||
Outcomes []CreateTicketOutcomeReq `json:"outcomes"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
TotalOdds float32 `json:"total_odds" example:"4.22"`
|
||||
Outcomes []CreateTicketOutcomeReq `json:"outcomes"`
|
||||
Amount float32 `json:"amount" example:"100.0"`
|
||||
}
|
||||
type CreateTicketRes struct {
|
||||
FastCode int64 `json:"fast_code" example:"1234"`
|
||||
|
|
@ -66,6 +65,7 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Too many odds/outcomes selected", nil, nil)
|
||||
}
|
||||
var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes))
|
||||
var totalOdds float32 = 1
|
||||
for _, outcome := range req.Outcomes {
|
||||
eventIDStr := strconv.FormatInt(outcome.EventID, 10)
|
||||
marketIDStr := strconv.FormatInt(outcome.MarketID, 10)
|
||||
|
|
@ -100,7 +100,7 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
rawBytes, err := json.Marshal(raw)
|
||||
err = json.Unmarshal(rawBytes, &rawOdd)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to unmarshal raw odd:", err)
|
||||
h.logger.Error("Failed to unmarshal raw odd:", "error", err)
|
||||
continue
|
||||
}
|
||||
if rawOdd.ID == oddIDStr {
|
||||
|
|
@ -114,7 +114,7 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
parsedOdd, err := strconv.ParseFloat(selectedOdd.Odds, 32)
|
||||
|
||||
totalOdds = totalOdds * float32(parsedOdd)
|
||||
outcomes = append(outcomes, domain.CreateTicketOutcome{
|
||||
EventID: outcome.EventID,
|
||||
OddID: outcome.OddID,
|
||||
|
|
@ -129,10 +129,9 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
|
|||
Expires: event.StartTime,
|
||||
})
|
||||
}
|
||||
|
||||
ticket, err := h.ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
TotalOdds: req.TotalOdds,
|
||||
TotalOdds: totalOdds,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTicketReq failed", "error", err)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
|
|
@ -25,6 +27,9 @@ type TransactionRes struct {
|
|||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
ApprovedBy *int64 `json:"approved_by" example:"1"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type CreateTransactionReq struct {
|
||||
|
|
@ -40,26 +45,36 @@ type CreateTransactionReq struct {
|
|||
AccountName string `json:"account_name"`
|
||||
AccountNumber string `json:"account_number"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
BranchID *int64 `json:"branch_id,omitempty" example:"1"`
|
||||
}
|
||||
|
||||
func convertTransaction(transaction domain.Transaction) TransactionRes {
|
||||
return TransactionRes{
|
||||
ID: transaction.ID,
|
||||
Amount: transaction.Amount.Float32(),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
Type: int64(transaction.Type),
|
||||
PaymentOption: transaction.PaymentOption,
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
Verified: transaction.Verified,
|
||||
newTransaction := TransactionRes{
|
||||
ID: transaction.ID,
|
||||
Amount: transaction.Amount.Float32(),
|
||||
BranchID: transaction.BranchID,
|
||||
CashierID: transaction.CashierID,
|
||||
BetID: transaction.BetID,
|
||||
Type: int64(transaction.Type),
|
||||
PaymentOption: transaction.PaymentOption,
|
||||
FullName: transaction.FullName,
|
||||
PhoneNumber: transaction.PhoneNumber,
|
||||
BankCode: transaction.BankCode,
|
||||
BeneficiaryName: transaction.BeneficiaryName,
|
||||
AccountName: transaction.AccountName,
|
||||
AccountNumber: transaction.AccountNumber,
|
||||
ReferenceNumber: transaction.ReferenceNumber,
|
||||
Verified: transaction.Verified,
|
||||
NumberOfOutcomes: transaction.NumberOfOutcomes,
|
||||
CreatedAt: transaction.CreatedAt,
|
||||
UpdatedAt: transaction.UpdatedAt,
|
||||
}
|
||||
|
||||
if transaction.ApprovedBy.Valid {
|
||||
newTransaction.ApprovedBy = &transaction.ApprovedBy.Value
|
||||
}
|
||||
|
||||
return newTransaction
|
||||
}
|
||||
|
||||
// CreateTransaction godoc
|
||||
|
|
@ -75,35 +90,17 @@ func convertTransaction(transaction domain.Transaction) TransactionRes {
|
|||
// @Router /transaction [post]
|
||||
func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
|
||||
userID := c.Locals("user_id").(int64)
|
||||
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
role := c.Locals("role").(domain.Role)
|
||||
// user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
||||
|
||||
if user.Role == domain.RoleCustomer {
|
||||
h.logger.Error("CreateTransactionReq failed")
|
||||
// TODO: Make a "Only Company" middleware auth and move this into that
|
||||
if role == domain.RoleCustomer {
|
||||
h.logger.Error("CreateTransactionReq failed due to unauthorized access")
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"error": "unauthorized access",
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Add validation to make sure that the bet hasn't already been cashed out by someone else
|
||||
var branchID int64
|
||||
if user.Role == domain.RoleAdmin || user.Role == domain.RoleBranchManager || user.Role == domain.RoleSuperAdmin {
|
||||
branch, err := h.branchSvc.GetBranchByID(c.Context(), 1)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTransactionReq no branches")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "This user type doesn't have branches", err, nil)
|
||||
}
|
||||
|
||||
branchID = branch.ID
|
||||
|
||||
} else {
|
||||
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), user.ID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTransactionReq failed, branch id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil)
|
||||
}
|
||||
branchID = branch.ID
|
||||
}
|
||||
|
||||
var req CreateTransactionReq
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("CreateTransaction failed to parse request", "error", err)
|
||||
|
|
@ -116,13 +113,51 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
// TODO: Validate the bet id and add the number of outcomes
|
||||
var branchID int64
|
||||
if role == domain.RoleAdmin || role == domain.RoleBranchManager || role == domain.RoleSuperAdmin {
|
||||
if req.BranchID == nil {
|
||||
h.logger.Error("CreateTransactionReq Branch ID is required for this user role")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID is required for this user role", nil, nil)
|
||||
}
|
||||
branch, err := h.branchSvc.GetBranchByID(c.Context(), *req.BranchID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTransactionReq no branches")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "cannot find Branch ID", err, nil)
|
||||
}
|
||||
|
||||
branchID = branch.ID
|
||||
|
||||
} else {
|
||||
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTransactionReq failed, branch id invalid")
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil)
|
||||
}
|
||||
branchID = branch.ID
|
||||
}
|
||||
|
||||
bet, err := h.betSvc.GetBetByID(c.Context(), req.BetID)
|
||||
if err != nil {
|
||||
h.logger.Error("CreateTransactionReq failed", "error", err)
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Bet ID invalid", err, nil)
|
||||
}
|
||||
|
||||
// if bet.Status != domain.OUTCOME_STATUS_WIN {
|
||||
// h.logger.Error("CreateTransactionReq failed, bet has not won")
|
||||
// return response.WriteJSON(c, fiber.StatusBadRequest, "User has not won bet", err, nil)
|
||||
// }
|
||||
|
||||
if bet.CashedOut {
|
||||
h.logger.Error(("Bet has already been cashed out"))
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "This bet has already been cashed out", err, nil)
|
||||
}
|
||||
|
||||
transaction, err := h.transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{
|
||||
BranchID: branchID,
|
||||
CashierID: userID,
|
||||
Amount: domain.ToCurrency(req.Amount),
|
||||
BetID: req.BetID,
|
||||
NumberOfOutcomes: 1,
|
||||
BetID: bet.ID,
|
||||
NumberOfOutcomes: int64(len(bet.Outcomes)),
|
||||
Type: domain.TransactionType(req.Type),
|
||||
PaymentOption: domain.PaymentOption(req.PaymentOption),
|
||||
FullName: req.FullName,
|
||||
|
|
@ -236,7 +271,7 @@ func (h *Handler) GetTransactionByID(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
type UpdateTransactionVerifiedReq struct {
|
||||
Verified bool `json:"verified" validate:"required" example:"true"`
|
||||
Verified bool `json:"verified" example:"true"`
|
||||
}
|
||||
|
||||
// UpdateTransactionVerified godoc
|
||||
|
|
@ -250,10 +285,12 @@ type UpdateTransactionVerifiedReq struct {
|
|||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /transaction/{id} [patch]
|
||||
// @Router /transaction/{id} [put]
|
||||
func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
||||
|
||||
transactionID := c.Params("id")
|
||||
userID := c.Locals("user_id").(int64)
|
||||
// companyID := c.Locals("company_id").(domain.ValidInt64)
|
||||
|
||||
id, err := strconv.ParseInt(transactionID, 10, 64)
|
||||
if err != nil {
|
||||
h.logger.Error("Invalid transaction ID", "transactionID", transactionID, "error", err)
|
||||
|
|
@ -266,11 +303,14 @@ func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
|
|||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
|
||||
}
|
||||
|
||||
h.logger.Info("Update Transaction Verified", slog.Bool("verified", req.Verified))
|
||||
|
||||
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
||||
}
|
||||
|
||||
err = h.transactionSvc.UpdateTransactionVerified(c.Context(), id, req.Verified)
|
||||
// TODO: make it so that only people within the company can verify a transaction
|
||||
err = h.transactionSvc.UpdateTransactionVerified(c.Context(), id, req.Verified, userID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to update transaction verification", "transactionID", id, "error", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transaction verification")
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Post("/transaction", a.authMiddleware, h.CreateTransaction)
|
||||
a.fiber.Get("/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
a.fiber.Get("/transaction/:id", a.authMiddleware, h.GetTransactionByID)
|
||||
a.fiber.Patch("/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||
a.fiber.Put("/transaction/:id", a.authMiddleware, h.UpdateTransactionVerified)
|
||||
|
||||
// Notification Routes
|
||||
a.fiber.Get("/notifications/ws/connect/:recipientID", h.ConnectSocket)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user