fix: integrating issues

This commit is contained in:
Samuel Tariku 2025-06-07 20:54:49 +03:00
parent 0dfd0c9d95
commit 62f7dd24eb
26 changed files with 420 additions and 167 deletions

View File

@ -65,6 +65,7 @@ CREATE TABLE IF NOT EXISTS tickets (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
amount BIGINT NOT NULL, amount BIGINT NOT NULL,
total_odds REAL NOT NULL, total_odds REAL NOT NULL,
IP VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
@ -262,9 +263,11 @@ FROM companies
CREATE VIEW branch_details AS CREATE VIEW branch_details AS
SELECT branches.*, SELECT branches.*,
CONCAT(users.first_name, ' ', users.last_name) AS manager_name, CONCAT(users.first_name, ' ', users.last_name) AS manager_name,
users.phone_number AS manager_phone_number users.phone_number AS manager_phone_number,
wallets.balance
FROM branches FROM branches
LEFT JOIN users ON branches.branch_manager_id = users.id; LEFT JOIN users ON branches.branch_manager_id = users.id
LEFT JOin wallets ON wallets.id = branches.wallet_id;
CREATE TABLE IF NOT EXISTS supported_operations ( CREATE TABLE IF NOT EXISTS supported_operations (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
@ -311,7 +314,6 @@ ADD CONSTRAINT fk_branch_operations_operations FOREIGN KEY (operation_id) REFERE
ALTER TABLE branch_cashiers ALTER TABLE branch_cashiers
ADD CONSTRAINT fk_branch_cashiers_users FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, ADD CONSTRAINT fk_branch_cashiers_users FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
ADD CONSTRAINT fk_branch_cashiers_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE; ADD CONSTRAINT fk_branch_cashiers_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE;
ALTER TABLE companies ALTER TABLE companies
ADD CONSTRAINT fk_companies_admin FOREIGN KEY (admin_id) REFERENCES users(id), ADD CONSTRAINT fk_companies_admin FOREIGN KEY (admin_id) REFERENCES users(id),
ADD CONSTRAINT fk_companies_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id) ON DELETE CASCADE; ADD CONSTRAINT fk_companies_wallet FOREIGN KEY (wallet_id) REFERENCES wallets(id) ON DELETE CASCADE;

View File

@ -2,14 +2,24 @@
SELECT users.* SELECT users.*
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE branch_cashiers.branch_id = $1; WHERE branch_cashiers.branch_id = $1;
-- name: GetAllCashiers :many -- name: GetAllCashiers :many
SELECT users.*, SELECT users.*,
branch_id branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id; JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id;
-- name: GetCashierByID :one -- name: GetCashierByID :one
SELECT users.*, SELECT users.*,
branch_id branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = $1; JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE users.id = $1;

View File

@ -1,6 +1,6 @@
-- name: CreateTicket :one -- name: CreateTicket :one
INSERT INTO tickets (amount, total_odds) INSERT INTO tickets (amount, total_odds, ip)
VALUES ($1, $2) VALUES ($1, $2, $3)
RETURNING *; RETURNING *;
-- name: CreateTicketOutcome :copyfrom -- name: CreateTicketOutcome :copyfrom
INSERT INTO ticket_outcomes ( INSERT INTO ticket_outcomes (
@ -42,6 +42,10 @@ WHERE id = $1;
SELECT * SELECT *
FROM ticket_outcomes FROM ticket_outcomes
WHERE ticket_id = $1; WHERE ticket_id = $1;
-- name: CountTicketByIP :one
SELECT count(id)
FROM tickets
WHERE IP = $1;
-- name: UpdateTicketOutcomeStatus :exec -- name: UpdateTicketOutcomeStatus :exec
UPDATE ticket_outcomes UPDATE ticket_outcomes
SET status = $1 SET status = $1

View File

@ -154,7 +154,7 @@ func (q *Queries) DeleteBranchOperation(ctx context.Context, arg DeleteBranchOpe
} }
const GetAllBranches = `-- name: GetAllBranches :many const GetAllBranches = `-- name: GetAllBranches :many
SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
FROM branch_details FROM branch_details
` `
@ -179,6 +179,7 @@ func (q *Queries) GetAllBranches(ctx context.Context) ([]BranchDetail, error) {
&i.UpdatedAt, &i.UpdatedAt,
&i.ManagerName, &i.ManagerName,
&i.ManagerPhoneNumber, &i.ManagerPhoneNumber,
&i.Balance,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -240,7 +241,7 @@ func (q *Queries) GetBranchByCashier(ctx context.Context, userID int64) (Branch,
} }
const GetBranchByCompanyID = `-- name: GetBranchByCompanyID :many const GetBranchByCompanyID = `-- name: GetBranchByCompanyID :many
SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
FROM branch_details FROM branch_details
WHERE company_id = $1 WHERE company_id = $1
` `
@ -266,6 +267,7 @@ func (q *Queries) GetBranchByCompanyID(ctx context.Context, companyID int64) ([]
&i.UpdatedAt, &i.UpdatedAt,
&i.ManagerName, &i.ManagerName,
&i.ManagerPhoneNumber, &i.ManagerPhoneNumber,
&i.Balance,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -278,7 +280,7 @@ func (q *Queries) GetBranchByCompanyID(ctx context.Context, companyID int64) ([]
} }
const GetBranchByID = `-- name: GetBranchByID :one const GetBranchByID = `-- name: GetBranchByID :one
SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
FROM branch_details FROM branch_details
WHERE id = $1 WHERE id = $1
` `
@ -298,12 +300,13 @@ func (q *Queries) GetBranchByID(ctx context.Context, id int64) (BranchDetail, er
&i.UpdatedAt, &i.UpdatedAt,
&i.ManagerName, &i.ManagerName,
&i.ManagerPhoneNumber, &i.ManagerPhoneNumber,
&i.Balance,
) )
return i, err return i, err
} }
const GetBranchByManagerID = `-- name: GetBranchByManagerID :many const GetBranchByManagerID = `-- name: GetBranchByManagerID :many
SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
FROM branch_details FROM branch_details
WHERE branch_manager_id = $1 WHERE branch_manager_id = $1
` `
@ -329,6 +332,7 @@ func (q *Queries) GetBranchByManagerID(ctx context.Context, branchManagerID int6
&i.UpdatedAt, &i.UpdatedAt,
&i.ManagerName, &i.ManagerName,
&i.ManagerPhoneNumber, &i.ManagerPhoneNumber,
&i.Balance,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -388,7 +392,7 @@ func (q *Queries) GetBranchOperations(ctx context.Context, branchID int64) ([]Ge
} }
const SearchBranchByName = `-- name: SearchBranchByName :many const SearchBranchByName = `-- name: SearchBranchByName :many
SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number SELECT id, name, location, wallet_id, branch_manager_id, company_id, is_self_owned, created_at, updated_at, manager_name, manager_phone_number, balance
FROM branch_details FROM branch_details
WHERE name ILIKE '%' || $1 || '%' WHERE name ILIKE '%' || $1 || '%'
` `
@ -414,6 +418,7 @@ func (q *Queries) SearchBranchByName(ctx context.Context, dollar_1 pgtype.Text)
&i.UpdatedAt, &i.UpdatedAt,
&i.ManagerName, &i.ManagerName,
&i.ManagerPhoneNumber, &i.ManagerPhoneNumber,
&i.Balance,
); err != nil { ); err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.29.0 // sqlc v1.28.0
// source: cashier.sql // source: cashier.sql
package dbgen package dbgen
@ -13,29 +13,36 @@ import (
const GetAllCashiers = `-- name: GetAllCashiers :many const GetAllCashiers = `-- name: GetAllCashiers :many
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by, SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by,
branch_id branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
` `
type GetAllCashiersRow struct { type GetAllCashiersRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
Password []byte `json:"password"` Password []byte `json:"password"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
SuspendedAt pgtype.Timestamptz `json:"suspended_at"` SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
ReferralCode pgtype.Text `json:"referral_code"` ReferralCode pgtype.Text `json:"referral_code"`
ReferredBy pgtype.Text `json:"referred_by"` ReferredBy pgtype.Text `json:"referred_by"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"`
BranchWallet int64 `json:"branch_wallet"`
BranchLocation string `json:"branch_location"`
} }
func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, error) { func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, error) {
@ -65,6 +72,9 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, erro
&i.ReferralCode, &i.ReferralCode,
&i.ReferredBy, &i.ReferredBy,
&i.BranchID, &i.BranchID,
&i.BranchName,
&i.BranchWallet,
&i.BranchLocation,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -78,33 +88,41 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, erro
const GetCashierByID = `-- name: GetCashierByID :one const GetCashierByID = `-- name: GetCashierByID :one
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by, SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by,
branch_id branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = $1 JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE users.id = $1
` `
type GetCashierByIDRow struct { type GetCashierByIDRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
Password []byte `json:"password"` Password []byte `json:"password"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
CompanyID pgtype.Int8 `json:"company_id"` CompanyID pgtype.Int8 `json:"company_id"`
SuspendedAt pgtype.Timestamptz `json:"suspended_at"` SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
ReferralCode pgtype.Text `json:"referral_code"` ReferralCode pgtype.Text `json:"referral_code"`
ReferredBy pgtype.Text `json:"referred_by"` ReferredBy pgtype.Text `json:"referred_by"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"`
BranchWallet int64 `json:"branch_wallet"`
BranchLocation string `json:"branch_location"`
} }
func (q *Queries) GetCashierByID(ctx context.Context, userID int64) (GetCashierByIDRow, error) { func (q *Queries) GetCashierByID(ctx context.Context, id int64) (GetCashierByIDRow, error) {
row := q.db.QueryRow(ctx, GetCashierByID, userID) row := q.db.QueryRow(ctx, GetCashierByID, id)
var i GetCashierByIDRow var i GetCashierByIDRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
@ -124,6 +142,9 @@ func (q *Queries) GetCashierByID(ctx context.Context, userID int64) (GetCashierB
&i.ReferralCode, &i.ReferralCode,
&i.ReferredBy, &i.ReferredBy,
&i.BranchID, &i.BranchID,
&i.BranchName,
&i.BranchWallet,
&i.BranchLocation,
) )
return i, err return i, err
} }
@ -132,6 +153,7 @@ const GetCashiersByBranch = `-- name: GetCashiersByBranch :many
SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by SELECT users.id, users.first_name, users.last_name, users.email, users.phone_number, users.role, users.password, users.email_verified, users.phone_verified, users.created_at, users.updated_at, users.company_id, users.suspended_at, users.suspended, users.referral_code, users.referred_by
FROM branch_cashiers FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE branch_cashiers.branch_id = $1 WHERE branch_cashiers.branch_id = $1
` `

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.29.0 // sqlc v1.28.0
// source: leagues.sql // source: leagues.sql
package dbgen package dbgen

View File

@ -138,6 +138,7 @@ type BranchDetail struct {
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
ManagerName interface{} `json:"manager_name"` ManagerName interface{} `json:"manager_name"`
ManagerPhoneNumber pgtype.Text `json:"manager_phone_number"` ManagerPhoneNumber pgtype.Text `json:"manager_phone_number"`
Balance pgtype.Int8 `json:"balance"`
} }
type BranchOperation struct { type BranchOperation struct {
@ -313,10 +314,19 @@ type SupportedOperation struct {
Description string `json:"description"` Description string `json:"description"`
} }
type Team struct {
ID string `json:"id"`
TeamName string `json:"team_name"`
Country pgtype.Text `json:"country"`
Bet365ID pgtype.Int4 `json:"bet365_id"`
LogoUrl pgtype.Text `json:"logo_url"`
}
type Ticket struct { type Ticket struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
} }
@ -342,6 +352,7 @@ type TicketWithOutcome struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
Outcomes []TicketOutcome `json:"outcomes"` Outcomes []TicketOutcome `json:"outcomes"`

View File

@ -11,24 +11,39 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
const CountTicketByIP = `-- name: CountTicketByIP :one
SELECT count(id)
FROM tickets
WHERE IP = $1
`
func (q *Queries) CountTicketByIP(ctx context.Context, ip string) (int64, error) {
row := q.db.QueryRow(ctx, CountTicketByIP, ip)
var count int64
err := row.Scan(&count)
return count, err
}
const CreateTicket = `-- name: CreateTicket :one const CreateTicket = `-- name: CreateTicket :one
INSERT INTO tickets (amount, total_odds) INSERT INTO tickets (amount, total_odds, ip)
VALUES ($1, $2) VALUES ($1, $2, $3)
RETURNING id, amount, total_odds, created_at, updated_at RETURNING id, amount, total_odds, ip, created_at, updated_at
` `
type CreateTicketParams struct { type CreateTicketParams struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"` TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
} }
func (q *Queries) CreateTicket(ctx context.Context, arg CreateTicketParams) (Ticket, error) { func (q *Queries) CreateTicket(ctx context.Context, arg CreateTicketParams) (Ticket, error) {
row := q.db.QueryRow(ctx, CreateTicket, arg.Amount, arg.TotalOdds) row := q.db.QueryRow(ctx, CreateTicket, arg.Amount, arg.TotalOdds, arg.Ip)
var i Ticket var i Ticket
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Ip,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
) )
@ -81,7 +96,7 @@ func (q *Queries) DeleteTicketOutcome(ctx context.Context, ticketID int64) error
} }
const GetAllTickets = `-- name: GetAllTickets :many const GetAllTickets = `-- name: GetAllTickets :many
SELECT id, amount, total_odds, created_at, updated_at, outcomes SELECT id, amount, total_odds, ip, created_at, updated_at, outcomes
FROM ticket_with_outcomes FROM ticket_with_outcomes
` `
@ -98,6 +113,7 @@ func (q *Queries) GetAllTickets(ctx context.Context) ([]TicketWithOutcome, error
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Ip,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
&i.Outcomes, &i.Outcomes,
@ -113,7 +129,7 @@ func (q *Queries) GetAllTickets(ctx context.Context) ([]TicketWithOutcome, error
} }
const GetTicketByID = `-- name: GetTicketByID :one const GetTicketByID = `-- name: GetTicketByID :one
SELECT id, amount, total_odds, created_at, updated_at, outcomes SELECT id, amount, total_odds, ip, created_at, updated_at, outcomes
FROM ticket_with_outcomes FROM ticket_with_outcomes
WHERE id = $1 WHERE id = $1
` `
@ -125,6 +141,7 @@ func (q *Queries) GetTicketByID(ctx context.Context, id int64) (TicketWithOutcom
&i.ID, &i.ID,
&i.Amount, &i.Amount,
&i.TotalOdds, &i.TotalOdds,
&i.Ip,
&i.CreatedAt, &i.CreatedAt,
&i.UpdatedAt, &i.UpdatedAt,
&i.Outcomes, &i.Outcomes,

View File

@ -15,6 +15,7 @@ type BranchDetail struct {
Name string Name string
Location string Location string
WalletID int64 WalletID int64
Balance Currency
BranchManagerID int64 BranchManagerID int64
CompanyID int64 CompanyID int64
IsSelfOwned bool IsSelfOwned bool

View File

@ -51,4 +51,5 @@ type GetTicket struct {
type CreateTicket struct { type CreateTicket struct {
Amount Currency Amount Currency
TotalOdds float32 TotalOdds float32
IP string
} }

View File

@ -71,17 +71,20 @@ type UpdateUserReferalCode struct {
} }
type GetCashier struct { type GetCashier struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
Email string `json:"email"` Email string `json:"email"`
PhoneNumber string `json:"phone_number"` PhoneNumber string `json:"phone_number"`
Role Role `json:"role"` Role Role `json:"role"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
SuspendedAt time.Time `json:"suspended_at"` SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"`
BranchWallet int64 `json:"branch_wallet"`
BranchLocation string `json:"branch_location"`
} }

View File

@ -30,6 +30,7 @@ func convertDBBranchDetail(dbBranch dbgen.BranchDetail) domain.BranchDetail {
IsSelfOwned: dbBranch.IsSelfOwned, IsSelfOwned: dbBranch.IsSelfOwned,
ManagerName: dbBranch.ManagerName.(string), ManagerName: dbBranch.ManagerName.(string),
ManagerPhoneNumber: dbBranch.ManagerPhoneNumber.String, ManagerPhoneNumber: dbBranch.ManagerPhoneNumber.String,
Balance: domain.Currency(dbBranch.Balance.Int64),
} }
} }

View File

@ -70,6 +70,7 @@ func convertCreateTicket(ticket domain.CreateTicket) dbgen.CreateTicketParams {
return dbgen.CreateTicketParams{ return dbgen.CreateTicketParams{
Amount: int64(ticket.Amount), Amount: int64(ticket.Amount),
TotalOdds: ticket.TotalOdds, TotalOdds: ticket.TotalOdds,
Ip: ticket.IP,
} }
} }
@ -123,6 +124,16 @@ func (s *Store) GetAllTickets(ctx context.Context) ([]domain.GetTicket, error) {
return result, nil return result, nil
} }
func (s *Store) CountTicketByIP(ctx context.Context, IP string) (int64, error) {
count, err := s.queries.CountTicketByIP(ctx, IP)
if err != nil {
return 0, err
}
return count, err
}
func (s *Store) UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error { func (s *Store) UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error {
err := s.queries.UpdateTicketOutcomeStatus(ctx, dbgen.UpdateTicketOutcomeStatusParams{ err := s.queries.UpdateTicketOutcomeStatus(ctx, dbgen.UpdateTicketOutcomeStatusParams{
Status: int32(status), Status: int32(status),

View File

@ -82,6 +82,10 @@ func (s *Store) GetUserByID(ctx context.Context, id int64) (domain.User, error)
UpdatedAt: user.UpdatedAt.Time, UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time, SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended, Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
}, nil }, nil
} }
func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, int64, error) { func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, int64, error) {
@ -118,6 +122,10 @@ func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.U
UpdatedAt: user.UpdatedAt.Time, UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time, SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended, Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
} }
} }
totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{ totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{
@ -130,29 +138,36 @@ func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.U
return userList, totalCount, nil return userList, totalCount, nil
} }
func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, error) { func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, int64, error) {
users, err := s.queries.GetAllCashiers(ctx) users, err := s.queries.GetAllCashiers(ctx)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
userList := make([]domain.GetCashier, len(users)) userList := make([]domain.GetCashier, len(users))
for i, user := range users { for i, user := range users {
userList[i] = domain.GetCashier{ userList[i] = domain.GetCashier{
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
Email: user.Email.String, Email: user.Email.String,
PhoneNumber: user.PhoneNumber.String, PhoneNumber: user.PhoneNumber.String,
Role: domain.Role(user.Role), Role: domain.Role(user.Role),
EmailVerified: user.EmailVerified, EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified, PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt.Time, CreatedAt: user.CreatedAt.Time,
UpdatedAt: user.UpdatedAt.Time, UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time, SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended, Suspended: user.Suspended,
BranchID: user.BranchID,
BranchName: user.BranchName,
BranchWallet: user.BranchWallet,
BranchLocation: user.BranchLocation,
} }
} }
return userList, nil totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{
Role: string(domain.RoleCashier),
})
return userList, totalCount, nil
} }
func (s *Store) GetCashierByID(ctx context.Context, cashierID int64) (domain.GetCashier, error) { func (s *Store) GetCashierByID(ctx context.Context, cashierID int64) (domain.GetCashier, error) {
@ -161,19 +176,22 @@ func (s *Store) GetCashierByID(ctx context.Context, cashierID int64) (domain.Get
return domain.GetCashier{}, err return domain.GetCashier{}, err
} }
return domain.GetCashier{ return domain.GetCashier{
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
Email: user.Email.String, Email: user.Email.String,
PhoneNumber: user.PhoneNumber.String, PhoneNumber: user.PhoneNumber.String,
Role: domain.Role(user.Role), Role: domain.Role(user.Role),
EmailVerified: user.EmailVerified, EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified, PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt.Time, CreatedAt: user.CreatedAt.Time,
UpdatedAt: user.UpdatedAt.Time, UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time, SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended, Suspended: user.Suspended,
BranchID: user.BranchID, BranchID: user.BranchID,
BranchName: user.BranchName,
BranchWallet: user.BranchWallet,
BranchLocation: user.BranchLocation,
}, nil }, nil
} }

View File

@ -11,6 +11,7 @@ type TicketStore interface {
CreateTicketOutcome(ctx context.Context, outcomes []domain.CreateTicketOutcome) (int64, error) CreateTicketOutcome(ctx context.Context, outcomes []domain.CreateTicketOutcome) (int64, error)
GetTicketByID(ctx context.Context, id int64) (domain.GetTicket, error) GetTicketByID(ctx context.Context, id int64) (domain.GetTicket, error)
GetAllTickets(ctx context.Context) ([]domain.GetTicket, error) GetAllTickets(ctx context.Context) ([]domain.GetTicket, error)
CountTicketByIP(ctx context.Context, IP string) (int64, error)
UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error
DeleteOldTickets(ctx context.Context) error DeleteOldTickets(ctx context.Context) error
DeleteTicket(ctx context.Context, id int64) error DeleteTicket(ctx context.Context, id int64) error

View File

@ -31,6 +31,10 @@ func (s *Service) GetAllTickets(ctx context.Context) ([]domain.GetTicket, error)
return s.ticketStore.GetAllTickets(ctx) return s.ticketStore.GetAllTickets(ctx)
} }
func (s *Service) CountTicketByIP(ctx context.Context, IP string) (int64, error) {
return s.ticketStore.CountTicketByIP(ctx, IP)
}
func (s *Service) UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error { func (s *Service) UpdateTicketOutcomeStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error {
return s.ticketStore.UpdateTicketOutcomeStatus(ctx, id, status) return s.ticketStore.UpdateTicketOutcomeStatus(ctx, id, status)
} }

View File

@ -71,7 +71,7 @@ func (s *Service) GetCashiersByBranch(ctx context.Context, branchID int64) ([]do
return s.userStore.GetCashiersByBranch(ctx, branchID) return s.userStore.GetCashiersByBranch(ctx, branchID)
} }
func (s *Service) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, error) { func (s *Service) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, int64, error){
return s.userStore.GetAllCashiers(ctx) return s.userStore.GetAllCashiers(ctx)
} }

View File

@ -11,7 +11,7 @@ type UserStore interface {
CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error) CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error)
GetUserByID(ctx context.Context, id int64) (domain.User, error) GetUserByID(ctx context.Context, id int64) (domain.User, error)
GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, int64, error) GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, int64, error)
GetAllCashiers(ctx context.Context) ([]domain.GetCashier, error) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, int64, error)
GetCashierByID(ctx context.Context, cashierID int64) (domain.GetCashier, error) GetCashierByID(ctx context.Context, cashierID int64) (domain.GetCashier, error)
GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error) GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error)
UpdateUser(ctx context.Context, user domain.UpdateUserReq) error UpdateUser(ctx context.Context, user domain.UpdateUserReq) error

View File

@ -2,25 +2,28 @@ package handlers
import ( import (
"errors" "errors"
"fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt" jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
// loginCustomerReq represents the request body for the LoginCustomer endpoint. // loginCustomerReq represents the request body for the LoginCustomer endpoint.
type loginCustomerReq struct { type loginCustomerReq struct {
Email string `json:"email" validate:"email" example:"john.doe@example.com"` Email string `json:"email" validate:"email" example:"john.doe@example.com"`
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"` PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
Password string `json:"password" validate:"required" example:"password123"` Password string `json:"password" validate:"required" example:"password123"`
} }
// loginCustomerRes represents the response body for the LoginCustomer endpoint. // loginCustomerRes represents the response body for the LoginCustomer endpoint.
type loginCustomerRes struct { type loginCustomerRes struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
Role string `json:"role"` Role string `json:"role"`
} }
// LoginCustomer godoc // LoginCustomer godoc
// @Summary Login customer // @Summary Login customer
// @Description Login customer // @Description Login customer
@ -74,8 +77,8 @@ func (h *Handler) LoginCustomer(c *fiber.Ctx) error {
} }
type refreshToken struct { type refreshToken struct {
AccessToken string `json:"access_token" validate:"required" example:"<jwt-token>"` AccessToken string `json:"access_token" validate:"required" example:"<jwt-token>"`
RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"` RefreshToken string `json:"refresh_token" validate:"required" example:"<refresh-token>"`
} }
// RefreshToken godoc // RefreshToken godoc
@ -124,6 +127,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
user, err := h.userSvc.GetUserByID(c.Context(), refreshToken.UserID) user, err := h.userSvc.GetUserByID(c.Context(), refreshToken.UserID)
fmt.Printf("user company id %v", user.CompanyID)
// Assuming the refreshed token includes userID and role info; adjust if needed // Assuming the refreshed token includes userID and role info; adjust if needed
accessToken, err := jwtutil.CreateJwt(user.ID, user.Role, user.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry) accessToken, err := jwtutil.CreateJwt(user.ID, user.Role, user.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
if err != nil { if err != nil {

View File

@ -58,15 +58,16 @@ type BranchRes struct {
} }
type BranchDetailRes struct { type BranchDetailRes struct {
ID int64 `json:"id" example:"1"` ID int64 `json:"id" example:"1"`
Name string `json:"name" example:"4-kilo Branch"` Name string `json:"name" example:"4-kilo Branch"`
Location string `json:"location" example:"Addis Ababa"` Location string `json:"location" example:"Addis Ababa"`
WalletID int64 `json:"wallet_id" example:"1"` WalletID int64 `json:"wallet_id" example:"1"`
BranchManagerID int64 `json:"branch_manager_id" example:"1"` BranchManagerID int64 `json:"branch_manager_id" example:"1"`
CompanyID int64 `json:"company_id" example:"1"` CompanyID int64 `json:"company_id" example:"1"`
IsSelfOwned bool `json:"is_self_owned" example:"false"` IsSelfOwned bool `json:"is_self_owned" example:"false"`
ManagerName string `json:"manager_name" example:"John Smith"` ManagerName string `json:"manager_name" example:"John Smith"`
ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"` ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"`
Balance float32 `json:"balance" example:"100.5"`
} }
func convertBranch(branch domain.Branch) BranchRes { func convertBranch(branch domain.Branch) BranchRes {
@ -92,6 +93,7 @@ func convertBranchDetail(branch domain.BranchDetail) BranchDetailRes {
IsSelfOwned: branch.IsSelfOwned, IsSelfOwned: branch.IsSelfOwned,
ManagerName: branch.ManagerName, ManagerName: branch.ManagerName,
ManagerPhoneNumber: branch.ManagerPhoneNumber, ManagerPhoneNumber: branch.ManagerPhoneNumber,
Balance: branch.Balance.Float32(),
} }
} }
@ -552,6 +554,50 @@ func (h *Handler) GetBranchCashiers(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Branch Cashiers retrieved successfully", result, nil) return response.WriteJSON(c, fiber.StatusOK, "Branch Cashiers retrieved successfully", result, nil)
} }
// GetBranchForCashier godoc
// @Summary Gets branch for cahier
// @Description Gets branch for cahier
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {object} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branchCashier [get]
func (h *Handler) GetBranchForCashier(c *fiber.Ctx) error {
cashierID, ok := c.Locals("user_id").(int64)
if !ok {
h.logger.Error("Invalid cashier ID in context")
return response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid cashier identification", nil, nil)
}
role, ok := c.Locals("role").(domain.Role)
if !ok || role != domain.RoleCashier {
h.logger.Error("Unauthorized access", "cashierID", cashierID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
}
branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
if !ok || !branchID.Valid {
h.logger.Error("Invalid branch ID in context", "cashierID", cashierID)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", nil, nil)
}
branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)
if err != nil {
h.logger.Error("Failed to get branch by ID", "branchID", branchID.Value, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch", err, nil)
}
res := convertBranchDetail(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch retrieved successfully", res, nil)
}
// GetBetByBranchID godoc // GetBetByBranchID godoc
// @Summary Gets bets by its branch id // @Summary Gets bets by its branch id
// @Description Gets bets by its branch id // @Description Gets bets by its branch id

View File

@ -85,20 +85,23 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
} }
type GetCashierRes struct { type GetCashierRes struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
Email string `json:"email"` Email string `json:"email"`
PhoneNumber string `json:"phone_number"` PhoneNumber string `json:"phone_number"`
Role domain.Role `json:"role"` Role domain.Role `json:"role"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
SuspendedAt time.Time `json:"suspended_at"` SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
LastLogin time.Time `json:"last_login"` LastLogin time.Time `json:"last_login"`
BranchID int64 `json:"branch_id"` BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"`
BranchWallet int64 `json:"branch_wallet"`
BranchLocation string `json:"branch_location"`
} }
// GetAllCashiers godoc // GetAllCashiers godoc
@ -139,7 +142,7 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
cashiers, total, err := h.userSvc.GetAllUsers(c.Context(), filter) cashiers, total, err := h.userSvc.GetAllCashiers(c.Context())
if err != nil { if err != nil {
h.logger.Error("GetAllCashiers failed", "error", err) h.logger.Error("GetAllCashiers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
@ -159,19 +162,23 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
} }
result = append(result, GetCashierRes{ result = append(result, GetCashierRes{
ID: cashier.ID, ID: cashier.ID,
FirstName: cashier.FirstName, FirstName: cashier.FirstName,
LastName: cashier.LastName, LastName: cashier.LastName,
Email: cashier.Email, Email: cashier.Email,
PhoneNumber: cashier.PhoneNumber, PhoneNumber: cashier.PhoneNumber,
Role: cashier.Role, Role: cashier.Role,
EmailVerified: cashier.EmailVerified, EmailVerified: cashier.EmailVerified,
PhoneVerified: cashier.PhoneVerified, PhoneVerified: cashier.PhoneVerified,
CreatedAt: cashier.CreatedAt, CreatedAt: cashier.CreatedAt,
UpdatedAt: cashier.UpdatedAt, UpdatedAt: cashier.UpdatedAt,
SuspendedAt: cashier.SuspendedAt, SuspendedAt: cashier.SuspendedAt,
Suspended: cashier.Suspended, Suspended: cashier.Suspended,
LastLogin: *lastLogin, LastLogin: *lastLogin,
BranchID: cashier.BranchID,
BranchName: cashier.BranchName,
BranchWallet: cashier.BranchWallet,
BranchLocation: cashier.BranchLocation,
}) })
} }
@ -215,6 +222,7 @@ func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
} }
user, err := h.userSvc.GetCashierByID(c.Context(), cashierID) user, err := h.userSvc.GetCashierByID(c.Context(), cashierID)
if err != nil { if err != nil {
h.logger.Error("Get User By ID failed", "error", err) h.logger.Error("Get User By ID failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
@ -230,20 +238,23 @@ func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
} }
res := GetCashierRes{ res := GetCashierRes{
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
Email: user.Email, Email: user.Email,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
Role: user.Role, Role: user.Role,
EmailVerified: user.EmailVerified, EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified, PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt, CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt, UpdatedAt: user.UpdatedAt,
SuspendedAt: user.SuspendedAt, SuspendedAt: user.SuspendedAt,
Suspended: user.Suspended, Suspended: user.Suspended,
LastLogin: *lastLogin, LastLogin: *lastLogin,
BranchID: user.BranchID, BranchID: user.BranchID,
BranchName: user.BranchName,
BranchWallet: user.BranchWallet,
BranchLocation: user.BranchLocation,
} }
return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil) return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
} }

View File

@ -65,6 +65,20 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
if len(req.Outcomes) > 30 { if len(req.Outcomes) > 30 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Too many odds/outcomes selected", nil, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Too many odds/outcomes selected", nil, nil)
} }
if req.Amount > 100000 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Cannot create a ticket with an amount above 100,000 birr", nil, nil)
}
clientIP := c.IP()
count, err := h.ticketSvc.CountTicketByIP(c.Context(), clientIP)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Error fetching user info", nil, nil)
}
if count > 50 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Ticket Limit reached", nil, nil)
}
var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes)) var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes))
var totalOdds float32 = 1 var totalOdds float32 = 1
for _, outcome := range req.Outcomes { for _, outcome := range req.Outcomes {
@ -129,10 +143,16 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
OddHandicap: selectedOdd.Handicap, OddHandicap: selectedOdd.Handicap,
Expires: event.StartTime, Expires: event.StartTime,
}) })
}
totalWinnings := req.Amount * totalOdds
if totalWinnings > 1000000 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Cannot create a ticket with 1,000,000 winnings", nil, nil)
} }
ticket, err := h.ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{ ticket, err := h.ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{
Amount: domain.ToCurrency(req.Amount), Amount: domain.ToCurrency(req.Amount),
TotalOdds: totalOdds, TotalOdds: totalOdds,
IP: clientIP,
}) })
if err != nil { if err != nil {
h.logger.Error("CreateTicketReq failed", "error", err) h.logger.Error("CreateTicketReq failed", "error", err)

View File

@ -265,3 +265,64 @@ func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil) return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil)
} }
// GetWalletForCashier godoc
// @Summary Get wallet for cashier
// @Description Get wallet for cashier
// @Tags cashier
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} UserProfileRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /cashierWallet [get]
func (h *Handler) GetWalletForCashier(c *fiber.Ctx) error {
cashierID, ok := c.Locals("user_id").(int64)
if !ok || cashierID == 0 {
h.logger.Error("Invalid cashier ID in context")
return response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid cashier identification", nil, nil)
}
role, ok := c.Locals("role").(domain.Role)
if !ok || role != domain.RoleCashier {
h.logger.Error("Unauthorized access", "cashierID", cashierID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
}
branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
if !ok || !branchID.Valid {
h.logger.Error("Invalid branch ID in context", "cashierID", cashierID)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", nil, nil)
}
branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)
if err != nil {
h.logger.Error("Failed to get branch by ID", "branchID", branchID.Value, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch", err, nil)
}
wallet, err := h.walletSvc.GetWalletByID(c.Context(), branch.WalletID)
if err != nil {
h.logger.Error("Failed to get wallet for cashier", "cashierID", cashierID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallet", err, nil)
}
res := WalletRes{
ID: wallet.ID,
Balance: wallet.Balance.Float32(),
IsWithdraw: wallet.IsWithdraw,
IsBettable: wallet.IsBettable,
IsTransferable: wallet.IsTransferable,
IsActive: wallet.IsActive,
UserID: wallet.UserID,
UpdatedAt: wallet.UpdatedAt,
CreatedAt: wallet.CreatedAt,
}
return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil)
}

View File

@ -39,7 +39,6 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
if refreshToken == "" { if refreshToken == "" {
// refreshToken = c.Cookies("refresh_token", "") // refreshToken = c.Cookies("refresh_token", "")
// return fiber.NewError(fiber.StatusUnauthorized, "Refresh token missing") // return fiber.NewError(fiber.StatusUnauthorized, "Refresh token missing")
} }

View File

@ -144,6 +144,7 @@ func (a *App) initAppRoutes() {
// /branch/search // /branch/search
// branch/wallet // branch/wallet
a.fiber.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers) a.fiber.Get("/branch/:id/cashiers", a.authMiddleware, h.GetBranchCashiers)
a.fiber.Get("/branchCashier", a.authMiddleware, h.GetBranchForCashier)
// Branch Operation // Branch Operation
a.fiber.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations) a.fiber.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
@ -182,6 +183,7 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/wallet/:id", h.GetWalletByID) a.fiber.Get("/wallet/:id", h.GetWalletByID)
a.fiber.Put("/wallet/:id", h.UpdateWalletActive) a.fiber.Put("/wallet/:id", h.UpdateWalletActive)
a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets) a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
a.fiber.Get("/cashierWallet", a.authMiddleware, h.GetWalletForCashier)
// Transfer // Transfer
// /transfer/wallet - transfer from one wallet to another wallet // /transfer/wallet - transfer from one wallet to another wallet

View File

@ -1,7 +1,6 @@
package ws package ws
import ( import (
"log"
"net/http" "net/http"
"sync" "sync"
@ -37,7 +36,7 @@ func (h *NotificationHub) Run() {
h.mu.Lock() h.mu.Lock()
h.Clients[client] = true h.Clients[client] = true
h.mu.Unlock() h.mu.Unlock()
log.Printf("Client registered: %d", client.RecipientID) // log.Printf("Client registered: %d", client.RecipientID)
case client := <-h.Unregister: case client := <-h.Unregister:
h.mu.Lock() h.mu.Lock()
if _, ok := h.Clients[client]; ok { if _, ok := h.Clients[client]; ok {
@ -45,7 +44,7 @@ func (h *NotificationHub) Run() {
client.Conn.Close() client.Conn.Close()
} }
h.mu.Unlock() h.mu.Unlock()
log.Printf("Client unregistered: %d", client.RecipientID) // log.Printf("Client unregistered: %d", client.RecipientID)
case message := <-h.Broadcast: case message := <-h.Broadcast:
h.mu.Lock() h.mu.Lock()
for client := range h.Clients { for client := range h.Clients {