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,
amount BIGINT NOT NULL,
total_odds REAL NOT NULL,
IP VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
@ -262,9 +263,11 @@ FROM companies
CREATE VIEW branch_details AS
SELECT branches.*,
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
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 (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
@ -311,7 +314,6 @@ ADD CONSTRAINT fk_branch_operations_operations FOREIGN KEY (operation_id) REFERE
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_branches FOREIGN KEY (branch_id) REFERENCES branches(id) ON DELETE CASCADE;
ALTER TABLE companies
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;

View File

@ -2,14 +2,24 @@
SELECT users.*
FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE branch_cashiers.branch_id = $1;
-- name: GetAllCashiers :many
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
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
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
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
INSERT INTO tickets (amount, total_odds)
VALUES ($1, $2)
INSERT INTO tickets (amount, total_odds, ip)
VALUES ($1, $2, $3)
RETURNING *;
-- name: CreateTicketOutcome :copyfrom
INSERT INTO ticket_outcomes (
@ -42,6 +42,10 @@ WHERE id = $1;
SELECT *
FROM ticket_outcomes
WHERE ticket_id = $1;
-- name: CountTicketByIP :one
SELECT count(id)
FROM tickets
WHERE IP = $1;
-- name: UpdateTicketOutcomeStatus :exec
UPDATE ticket_outcomes
SET status = $1

View File

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

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// sqlc v1.28.0
// source: cashier.sql
package dbgen
@ -13,9 +13,13 @@ import (
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,
branch_id
branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
`
type GetAllCashiersRow struct {
@ -36,6 +40,9 @@ type GetAllCashiersRow struct {
ReferralCode pgtype.Text `json:"referral_code"`
ReferredBy pgtype.Text `json:"referred_by"`
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) {
@ -65,6 +72,9 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, erro
&i.ReferralCode,
&i.ReferredBy,
&i.BranchID,
&i.BranchName,
&i.BranchWallet,
&i.BranchLocation,
); err != nil {
return nil, err
}
@ -78,9 +88,14 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]GetAllCashiersRow, erro
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,
branch_id
branch_id,
branches.name AS branch_name,
branches.wallet_id AS branch_wallet,
branches.location As branch_location
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 {
@ -101,10 +116,13 @@ type GetCashierByIDRow struct {
ReferralCode pgtype.Text `json:"referral_code"`
ReferredBy pgtype.Text `json:"referred_by"`
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) {
row := q.db.QueryRow(ctx, GetCashierByID, userID)
func (q *Queries) GetCashierByID(ctx context.Context, id int64) (GetCashierByIDRow, error) {
row := q.db.QueryRow(ctx, GetCashierByID, id)
var i GetCashierByIDRow
err := row.Scan(
&i.ID,
@ -124,6 +142,9 @@ func (q *Queries) GetCashierByID(ctx context.Context, userID int64) (GetCashierB
&i.ReferralCode,
&i.ReferredBy,
&i.BranchID,
&i.BranchName,
&i.BranchWallet,
&i.BranchLocation,
)
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
FROM branch_cashiers
JOIN users ON branch_cashiers.user_id = users.id
JOIN branches ON branches.id = branch_id
WHERE branch_cashiers.branch_id = $1
`

View File

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

View File

@ -138,6 +138,7 @@ type BranchDetail struct {
UpdatedAt pgtype.Timestamp `json:"updated_at"`
ManagerName interface{} `json:"manager_name"`
ManagerPhoneNumber pgtype.Text `json:"manager_phone_number"`
Balance pgtype.Int8 `json:"balance"`
}
type BranchOperation struct {
@ -313,10 +314,19 @@ type SupportedOperation struct {
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 {
ID int64 `json:"id"`
Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
}
@ -342,6 +352,7 @@ type TicketWithOutcome struct {
ID int64 `json:"id"`
Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"`
Outcomes []TicketOutcome `json:"outcomes"`

View File

@ -11,24 +11,39 @@ import (
"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
INSERT INTO tickets (amount, total_odds)
VALUES ($1, $2)
RETURNING id, amount, total_odds, created_at, updated_at
INSERT INTO tickets (amount, total_odds, ip)
VALUES ($1, $2, $3)
RETURNING id, amount, total_odds, ip, created_at, updated_at
`
type CreateTicketParams struct {
Amount int64 `json:"amount"`
TotalOdds float32 `json:"total_odds"`
Ip string `json:"ip"`
}
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
err := row.Scan(
&i.ID,
&i.Amount,
&i.TotalOdds,
&i.Ip,
&i.CreatedAt,
&i.UpdatedAt,
)
@ -81,7 +96,7 @@ func (q *Queries) DeleteTicketOutcome(ctx context.Context, ticketID int64) error
}
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
`
@ -98,6 +113,7 @@ func (q *Queries) GetAllTickets(ctx context.Context) ([]TicketWithOutcome, error
&i.ID,
&i.Amount,
&i.TotalOdds,
&i.Ip,
&i.CreatedAt,
&i.UpdatedAt,
&i.Outcomes,
@ -113,7 +129,7 @@ func (q *Queries) GetAllTickets(ctx context.Context) ([]TicketWithOutcome, error
}
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
WHERE id = $1
`
@ -125,6 +141,7 @@ func (q *Queries) GetTicketByID(ctx context.Context, id int64) (TicketWithOutcom
&i.ID,
&i.Amount,
&i.TotalOdds,
&i.Ip,
&i.CreatedAt,
&i.UpdatedAt,
&i.Outcomes,

View File

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

View File

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

View File

@ -84,4 +84,7 @@ type GetCashier struct {
SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"`
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,
ManagerName: dbBranch.ManagerName.(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{
Amount: int64(ticket.Amount),
TotalOdds: ticket.TotalOdds,
Ip: ticket.IP,
}
}
@ -123,6 +124,16 @@ func (s *Store) GetAllTickets(ctx context.Context) ([]domain.GetTicket, error) {
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 {
err := s.queries.UpdateTicketOutcomeStatus(ctx, dbgen.UpdateTicketOutcomeStatusParams{
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,
SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
}, nil
}
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,
SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended,
CompanyID: domain.ValidInt64{
Value: user.CompanyID.Int64,
Valid: user.CompanyID.Valid,
},
}
}
totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{
@ -130,10 +138,10 @@ func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.U
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)
if err != nil {
return nil, err
return nil, 0, err
}
userList := make([]domain.GetCashier, len(users))
for i, user := range users {
@ -150,9 +158,16 @@ func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, error)
UpdatedAt: user.UpdatedAt.Time,
SuspendedAt: user.SuspendedAt.Time,
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) {
@ -174,6 +189,9 @@ func (s *Store) GetCashierByID(ctx context.Context, cashierID int64) (domain.Get
SuspendedAt: user.SuspendedAt.Time,
Suspended: user.Suspended,
BranchID: user.BranchID,
BranchName: user.BranchName,
BranchWallet: user.BranchWallet,
BranchLocation: user.BranchLocation,
}, nil
}

View File

@ -11,6 +11,7 @@ type TicketStore interface {
CreateTicketOutcome(ctx context.Context, outcomes []domain.CreateTicketOutcome) (int64, error)
GetTicketByID(ctx context.Context, id int64) (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
DeleteOldTickets(ctx context.Context) 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)
}
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 {
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)
}
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)
}

View File

@ -11,7 +11,7 @@ type UserStore interface {
CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error)
GetUserByID(ctx context.Context, id int64) (domain.User, 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)
GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error)
UpdateUser(ctx context.Context, user domain.UpdateUserReq) error

View File

@ -2,12 +2,14 @@ package handlers
import (
"errors"
"fmt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
)
// loginCustomerReq represents the request body for the LoginCustomer endpoint.
type loginCustomerReq struct {
Email string `json:"email" validate:"email" example:"john.doe@example.com"`
@ -21,6 +23,7 @@ type loginCustomerRes struct {
RefreshToken string `json:"refresh_token"`
Role string `json:"role"`
}
// LoginCustomer godoc
// @Summary Login customer
// @Description Login customer
@ -124,6 +127,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
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
accessToken, err := jwtutil.CreateJwt(user.ID, user.Role, user.CompanyID, h.jwtConfig.JwtAccessKey, h.jwtConfig.JwtAccessExpiry)
if err != nil {

View File

@ -67,6 +67,7 @@ type BranchDetailRes struct {
IsSelfOwned bool `json:"is_self_owned" example:"false"`
ManagerName string `json:"manager_name" example:"John Smith"`
ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"`
Balance float32 `json:"balance" example:"100.5"`
}
func convertBranch(branch domain.Branch) BranchRes {
@ -92,6 +93,7 @@ func convertBranchDetail(branch domain.BranchDetail) BranchDetailRes {
IsSelfOwned: branch.IsSelfOwned,
ManagerName: branch.ManagerName,
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)
}
// 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
// @Summary Gets bets by its branch id
// @Description Gets bets by its branch id

View File

@ -99,6 +99,9 @@ type GetCashierRes struct {
Suspended bool `json:"suspended"`
LastLogin time.Time `json:"last_login"`
BranchID int64 `json:"branch_id"`
BranchName string `json:"branch_name"`
BranchWallet int64 `json:"branch_wallet"`
BranchLocation string `json:"branch_location"`
}
// GetAllCashiers godoc
@ -139,7 +142,7 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
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 {
h.logger.Error("GetAllCashiers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
@ -172,6 +175,10 @@ func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
SuspendedAt: cashier.SuspendedAt,
Suspended: cashier.Suspended,
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)
if err != nil {
h.logger.Error("Get User By ID failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
@ -244,6 +252,9 @@ func (h *Handler) GetCashierByID(c *fiber.Ctx) error {
Suspended: user.Suspended,
LastLogin: *lastLogin,
BranchID: user.BranchID,
BranchName: user.BranchName,
BranchWallet: user.BranchWallet,
BranchLocation: user.BranchLocation,
}
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 {
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 totalOdds float32 = 1
for _, outcome := range req.Outcomes {
@ -129,10 +143,16 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
OddHandicap: selectedOdd.Handicap,
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{
Amount: domain.ToCurrency(req.Amount),
TotalOdds: totalOdds,
IP: clientIP,
})
if err != nil {
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)
}
// 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 == "" {
// refreshToken = c.Cookies("refresh_token", "")
// return fiber.NewError(fiber.StatusUnauthorized, "Refresh token missing")
}

View File

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

View File

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