feat: add the bet winning to user wallet

This commit is contained in:
Samuel Tariku 2025-05-30 19:38:59 +03:00
parent 95eaed18ad
commit 542400bcaf
21 changed files with 291 additions and 72 deletions

View File

@ -47,6 +47,7 @@ CREATE TABLE IF NOT EXISTS bets (
status INT NOT NULL,
full_name VARCHAR(255) NOT NULL,
phone_number VARCHAR(255) NOT NULL,
company_id BIGINT,
branch_id BIGINT,
user_id BIGINT,
cashed_out BOOLEAN DEFAULT FALSE NOT NULL,
@ -341,7 +342,8 @@ INSERT INTO users (
created_at,
updated_at,
suspended_at,
suspended
suspended,
company_id
)
VALUES (
'Test',
@ -355,7 +357,8 @@ VALUES (
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP,
NULL,
FALSE
FALSE,
1
);
INSERT INTO users (
first_name,

View File

@ -8,9 +8,10 @@ INSERT INTO bets (
branch_id,
user_id,
is_shop_bet,
cashout_id
cashout_id,
company_id
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING *;
-- name: CreateBetOutcome :copyfrom
INSERT INTO bet_outcomes (
@ -45,7 +46,19 @@ VALUES (
);
-- name: GetAllBets :many
SELECT *
FROM bet_with_outcomes;
FROM bet_with_outcomes
wHERE (
branch_id = $1
OR $1 IS NULL
)
AND (
company_id = $2
OR $2 IS NULL
)
AND (
user_id = $3
OR $3 IS NULL
);
-- name: GetBetByID :one
SELECT *
FROM bet_with_outcomes

View File

@ -42,7 +42,19 @@ VALUES (
RETURNING *;
-- name: GetAllTransactions :many
SELECT *
FROM transactions;
FROM transactions
wHERE (
branch_id = sqlc.narg('branch_id')
OR sqlc.narg('branch_id') IS NULL
)
AND (
company_id = sqlc.narg('company_id')
OR sqlc.narg('company_id') IS NULL
)
AND (
cashier_id = sqlc.narg('cashier_id')
OR sqlc.narg('cashier_id') IS NULL
);
-- name: GetTransactionByID :one
SELECT *
FROM transactions

View File

@ -21,10 +21,11 @@ INSERT INTO bets (
branch_id,
user_id,
is_shop_bet,
cashout_id
cashout_id,
company_id
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet
`
type CreateBetParams struct {
@ -37,6 +38,7 @@ type CreateBetParams struct {
UserID pgtype.Int8 `json:"user_id"`
IsShopBet bool `json:"is_shop_bet"`
CashoutID string `json:"cashout_id"`
CompanyID pgtype.Int8 `json:"company_id"`
}
func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, error) {
@ -50,6 +52,7 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
arg.UserID,
arg.IsShopBet,
arg.CashoutID,
arg.CompanyID,
)
var i Bet
err := row.Scan(
@ -59,6 +62,7 @@ func (q *Queries) CreateBet(ctx context.Context, arg CreateBetParams) (Bet, erro
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
@ -107,12 +111,30 @@ func (q *Queries) DeleteBetOutcome(ctx context.Context, betID int64) error {
}
const GetAllBets = `-- name: GetAllBets :many
SELECT id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
FROM bet_with_outcomes
wHERE (
branch_id = $1
OR $1 IS NULL
)
AND (
company_id = $2
OR $2 IS NULL
)
AND (
user_id = $3
OR $3 IS NULL
)
`
func (q *Queries) GetAllBets(ctx context.Context) ([]BetWithOutcome, error) {
rows, err := q.db.Query(ctx, GetAllBets)
type GetAllBetsParams struct {
BranchID pgtype.Int8 `json:"branch_id"`
CompanyID pgtype.Int8 `json:"company_id"`
UserID pgtype.Int8 `json:"user_id"`
}
func (q *Queries) GetAllBets(ctx context.Context, arg GetAllBetsParams) ([]BetWithOutcome, error) {
rows, err := q.db.Query(ctx, GetAllBets, arg.BranchID, arg.CompanyID, arg.UserID)
if err != nil {
return nil, err
}
@ -127,6 +149,7 @@ func (q *Queries) GetAllBets(ctx context.Context) ([]BetWithOutcome, error) {
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
@ -147,7 +170,7 @@ func (q *Queries) GetAllBets(ctx context.Context) ([]BetWithOutcome, error) {
}
const GetBetByBranchID = `-- name: GetBetByBranchID :many
SELECT id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
FROM bet_with_outcomes
WHERE branch_id = $1
`
@ -168,6 +191,7 @@ func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
@ -188,7 +212,7 @@ func (q *Queries) GetBetByBranchID(ctx context.Context, branchID pgtype.Int8) ([
}
const GetBetByCashoutID = `-- name: GetBetByCashoutID :one
SELECT id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
FROM bet_with_outcomes
WHERE cashout_id = $1
`
@ -203,6 +227,7 @@ func (q *Queries) GetBetByCashoutID(ctx context.Context, cashoutID string) (BetW
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
@ -216,7 +241,7 @@ func (q *Queries) GetBetByCashoutID(ctx context.Context, cashoutID string) (BetW
}
const GetBetByID = `-- name: GetBetByID :one
SELECT id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
FROM bet_with_outcomes
WHERE id = $1
`
@ -231,6 +256,7 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,
@ -244,7 +270,7 @@ func (q *Queries) GetBetByID(ctx context.Context, id int64) (BetWithOutcome, err
}
const GetBetByUserID = `-- name: GetBetByUserID :many
SELECT id, amount, total_odds, status, full_name, phone_number, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
SELECT id, amount, total_odds, status, full_name, phone_number, company_id, branch_id, user_id, cashed_out, cashout_id, created_at, updated_at, is_shop_bet, outcomes
FROM bet_with_outcomes
WHERE user_id = $1
`
@ -265,6 +291,7 @@ func (q *Queries) GetBetByUserID(ctx context.Context, userID pgtype.Int8) ([]Bet
&i.Status,
&i.FullName,
&i.PhoneNumber,
&i.CompanyID,
&i.BranchID,
&i.UserID,
&i.CashedOut,

View File

@ -62,6 +62,7 @@ type Bet struct {
Status int32 `json:"status"`
FullName string `json:"full_name"`
PhoneNumber string `json:"phone_number"`
CompanyID pgtype.Int8 `json:"company_id"`
BranchID pgtype.Int8 `json:"branch_id"`
UserID pgtype.Int8 `json:"user_id"`
CashedOut bool `json:"cashed_out"`
@ -96,6 +97,7 @@ type BetWithOutcome struct {
Status int32 `json:"status"`
FullName string `json:"full_name"`
PhoneNumber string `json:"phone_number"`
CompanyID pgtype.Int8 `json:"company_id"`
BranchID pgtype.Int8 `json:"branch_id"`
UserID pgtype.Int8 `json:"user_id"`
CashedOut bool `json:"cashed_out"`
@ -382,6 +384,32 @@ type User struct {
ReferredBy pgtype.Text `json:"referred_by"`
}
type UserGameInteraction struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
GameID int64 `json:"game_id"`
InteractionType string `json:"interaction_type"`
Amount pgtype.Numeric `json:"amount"`
DurationSeconds pgtype.Int4 `json:"duration_seconds"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type VirtualGame struct {
ID int64 `json:"id"`
Name string `json:"name"`
Provider string `json:"provider"`
Category string `json:"category"`
MinBet pgtype.Numeric `json:"min_bet"`
MaxBet pgtype.Numeric `json:"max_bet"`
Volatility string `json:"volatility"`
Rtp pgtype.Numeric `json:"rtp"`
IsFeatured pgtype.Bool `json:"is_featured"`
PopularityScore pgtype.Int4 `json:"popularity_score"`
ThumbnailUrl pgtype.Text `json:"thumbnail_url"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type VirtualGameSession struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`

View File

@ -130,10 +130,28 @@ func (q *Queries) CreateTransaction(ctx context.Context, arg CreateTransactionPa
const GetAllTransactions = `-- name: GetAllTransactions :many
SELECT id, amount, branch_id, company_id, cashier_id, cashier_name, 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, approver_name, branch_location, branch_name, created_at, updated_at
FROM transactions
wHERE (
branch_id = $1
OR $1 IS NULL
)
AND (
company_id = $2
OR $2 IS NULL
)
AND (
cashier_id = $3
OR $3 IS NULL
)
`
func (q *Queries) GetAllTransactions(ctx context.Context) ([]Transaction, error) {
rows, err := q.db.Query(ctx, GetAllTransactions)
type GetAllTransactionsParams struct {
BranchID pgtype.Int8 `json:"branch_id"`
CompanyID pgtype.Int8 `json:"company_id"`
CashierID pgtype.Int8 `json:"cashier_id"`
}
func (q *Queries) GetAllTransactions(ctx context.Context, arg GetAllTransactionsParams) ([]Transaction, error) {
rows, err := q.db.Query(ctx, GetAllTransactions, arg.BranchID, arg.CompanyID, arg.CashierID)
if err != nil {
return nil, err
}

View File

@ -48,6 +48,7 @@ type Bet struct {
FullName string
PhoneNumber string
BranchID ValidInt64 // Can Be Nullable
CompanyID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool
CashedOut bool
@ -55,6 +56,12 @@ type Bet struct {
CreatedAt time.Time
}
type BetFilter struct {
BranchID ValidInt64 // Can Be Nullable
CompanyID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
}
type GetBet struct {
ID int64
Amount Currency
@ -63,6 +70,7 @@ type GetBet struct {
FullName string
PhoneNumber string
BranchID ValidInt64 // Can Be Nullable
CompanyID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool
CashedOut bool
@ -77,6 +85,7 @@ type CreateBet struct {
Status OutcomeStatus
FullName string
PhoneNumber string
CompanyID ValidInt64 // Can Be Nullable
BranchID ValidInt64 // Can Be Nullable
UserID ValidInt64 // Can Be Nullable
IsShopBet bool
@ -164,3 +173,4 @@ func ConvertBet(bet GetBet) BetRes {
CreatedAt: bet.CreatedAt,
}
}

View File

@ -47,3 +47,14 @@ func (m Currency) String() string {
x = x / 100
return fmt.Sprintf("$%.2f", x)
}
func CalculateWinnings(amount Currency, totalOdds float32) Currency {
vat := amount.Float32() * 0.15
stakeAfterVat := amount.Float32() - vat
possibleWin := stakeAfterVat * totalOdds
incomeTax := possibleWin * 0.15
return ToCurrency(possibleWin - incomeTax)
}

View File

@ -47,6 +47,12 @@ type Transaction struct {
UpdatedAt time.Time
CreatedAt time.Time
}
type TransactionFilter struct {
CompanyID ValidInt64
BranchID ValidInt64
CashierID ValidInt64
}
type CreateTransaction struct {
Amount Currency
BranchID int64

View File

@ -22,6 +22,10 @@ func convertDBBet(bet dbgen.Bet) domain.Bet {
Value: bet.BranchID.Int64,
Valid: bet.BranchID.Valid,
},
CompanyID: domain.ValidInt64{
Value: bet.CompanyID.Int64,
Valid: bet.CompanyID.Valid,
},
UserID: domain.ValidInt64{
Value: bet.UserID.Int64,
Valid: bet.UserID.Valid,
@ -111,6 +115,7 @@ func convertCreateBet(bet domain.CreateBet) dbgen.CreateBetParams {
Status: int32(bet.Status),
FullName: bet.FullName,
PhoneNumber: bet.PhoneNumber,
BranchID: pgtype.Int8{
Int64: bet.BranchID.Value,
Valid: bet.BranchID.Valid,
@ -168,8 +173,21 @@ func (s *Store) GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet
return convertDBBetWithOutcomes(bet), nil
}
func (s *Store) GetAllBets(ctx context.Context) ([]domain.GetBet, error) {
bets, err := s.queries.GetAllBets(ctx)
func (s *Store) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
bets, err := s.queries.GetAllBets(ctx, dbgen.GetAllBetsParams{
BranchID: pgtype.Int8{
Int64: filter.BranchID.Value,
Valid: filter.BranchID.Valid,
},
CompanyID: pgtype.Int8{
Int64: filter.CompanyID.Value,
Valid: filter.CompanyID.Valid,
},
UserID: pgtype.Int8{
Int64: filter.UserID.Value,
Valid: filter.UserID.Valid,
},
})
if err != nil {
return nil, err
}

View File

@ -84,8 +84,21 @@ func (s *Store) GetTransactionByID(ctx context.Context, id int64) (domain.Transa
return convertDBTransaction(transaction), nil
}
func (s *Store) GetAllTransactions(ctx context.Context) ([]domain.Transaction, error) {
transaction, err := s.queries.GetAllTransactions(ctx)
func (s *Store) GetAllTransactions(ctx context.Context, filter domain.TransactionFilter) ([]domain.Transaction, error) {
transaction, err := s.queries.GetAllTransactions(ctx, dbgen.GetAllTransactionsParams{
BranchID: pgtype.Int8{
Int64: filter.BranchID.Value,
Valid: filter.BranchID.Valid,
},
CompanyID: pgtype.Int8{
Int64: filter.CompanyID.Value,
Valid: filter.CompanyID.Valid,
},
CashierID: pgtype.Int8{
Int64: filter.CashierID.Value,
Valid: filter.CashierID.Valid,
},
})
if err != nil {
return nil, err

View File

@ -11,7 +11,7 @@ type BetStore interface {
CreateBetOutcome(ctx context.Context, outcomes []domain.CreateBetOutcome) (int64, error)
GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error)
GetBetByID(ctx context.Context, id int64) (domain.GetBet, error)
GetAllBets(ctx context.Context) ([]domain.GetBet, error)
GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error)
GetBetByBranchID(ctx context.Context, BranchID int64) ([]domain.GetBet, error)
GetBetByUserID(ctx context.Context, UserID int64) ([]domain.GetBet, error)
GetBetOutcomeByEventID(ctx context.Context, eventID int64) ([]domain.BetOutcome, error)

View File

@ -197,6 +197,11 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
Value: branch.ID,
Valid: true,
}
newBet.CompanyID = domain.ValidInt64{
Value: branch.CompanyID,
Valid: true,
}
newBet.UserID = domain.ValidInt64{
Value: userID,
Valid: true,
@ -227,6 +232,10 @@ func (s *Service) PlaceBet(ctx context.Context, req domain.CreateBetReq, userID
Value: branch.ID,
Valid: true,
}
newBet.CompanyID = domain.ValidInt64{
Value: branch.CompanyID,
Valid: true,
}
newBet.UserID = domain.ValidInt64{
Value: userID,
Valid: true,
@ -483,8 +492,8 @@ func (s *Service) GetBetByID(ctx context.Context, id int64) (domain.GetBet, erro
func (s *Service) GetBetByCashoutID(ctx context.Context, id string) (domain.GetBet, error) {
return s.betStore.GetBetByCashoutID(ctx, id)
}
func (s *Service) GetAllBets(ctx context.Context) ([]domain.GetBet, error) {
return s.betStore.GetAllBets(ctx)
func (s *Service) GetAllBets(ctx context.Context, filter domain.BetFilter) ([]domain.GetBet, error) {
return s.betStore.GetAllBets(ctx, filter)
}
func (s *Service) GetBetByBranchID(ctx context.Context, branchID int64) ([]domain.GetBet, error) {
@ -500,6 +509,41 @@ func (s *Service) UpdateCashOut(ctx context.Context, id int64, cashedOut bool) e
}
func (s *Service) UpdateStatus(ctx context.Context, id int64, status domain.OutcomeStatus) error {
bet, err := s.GetBetByID(ctx, id)
if err != nil {
s.logger.Error("Failed to update bet status. Invalid bet id")
return err
}
if bet.IsShopBet ||
status == domain.OUTCOME_STATUS_ERROR ||
status == domain.OUTCOME_STATUS_PENDING ||
status == domain.OUTCOME_STATUS_LOSS {
return s.betStore.UpdateStatus(ctx, id, status)
}
customerWallet, err := s.walletSvc.GetCustomerWallet(ctx, id)
if err != nil {
s.logger.Error("Failed to update bet status. Invalid customer wallet id")
return err
}
var amount domain.Currency
if status == domain.OUTCOME_STATUS_WIN {
amount = domain.CalculateWinnings(bet.Amount, bet.TotalOdds)
} else if status == domain.OUTCOME_STATUS_HALF {
amount = (domain.CalculateWinnings(bet.Amount, bet.TotalOdds)) / 2
} else {
amount = bet.Amount
}
err = s.walletSvc.AddToWallet(ctx, customerWallet.RegularID, amount)
if err != nil {
s.logger.Error("Failed to update bet status. Failed to update user wallet")
return err
}
return s.betStore.UpdateStatus(ctx, id, status)
}

View File

@ -9,7 +9,7 @@ import (
type TransactionStore interface {
CreateTransaction(ctx context.Context, transaction domain.CreateTransaction) (domain.Transaction, error)
GetTransactionByID(ctx context.Context, id int64) (domain.Transaction, error)
GetAllTransactions(ctx context.Context) ([]domain.Transaction, error)
GetAllTransactions(ctx context.Context, filter domain.TransactionFilter) ([]domain.Transaction, error)
GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error)
UpdateTransactionVerified(ctx context.Context, id int64, verified bool, approvedBy int64, approverName string) error
}

View File

@ -22,8 +22,8 @@ func (s *Service) CreateTransaction(ctx context.Context, transaction domain.Crea
func (s *Service) GetTransactionByID(ctx context.Context, id int64) (domain.Transaction, error) {
return s.transactionStore.GetTransactionByID(ctx, id)
}
func (s *Service) GetAllTransactions(ctx context.Context) ([]domain.Transaction, error) {
return s.transactionStore.GetAllTransactions(ctx)
func (s *Service) GetAllTransactions(ctx context.Context, filter domain.TransactionFilter) ([]domain.Transaction, error) {
return s.transactionStore.GetAllTransactions(ctx, filter)
}
func (s *Service) GetTransactionByBranch(ctx context.Context, id int64) ([]domain.Transaction, error) {
return s.transactionStore.GetTransactionByBranch(ctx, id)

View File

@ -21,22 +21,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
spec string
task func()
}{
{
spec: "0 0 * * * *", // Every 1 hour
task: func() {
if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
log.Printf("FetchUpcomingEvents error: %v", err)
}
},
},
{
spec: "0 */15 * * * *", // Every 15 minutes
task: func() {
if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
log.Printf("FetchNonLiveOdds error: %v", err)
}
},
},
// {
// spec: "0 0 * * * *", // Every 1 hour
// task: func() {
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
// log.Printf("FetchUpcomingEvents error: %v", err)
// }
// },
// },
// {
// spec: "0 */15 * * * *", // Every 15 minutes
// task: func() {
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
// log.Printf("FetchNonLiveOdds error: %v", err)
// }
// },
// },
{
spec: "0 */15 * * * *", // Every 15 Minutes
task: func() {

View File

@ -150,7 +150,13 @@ func (h *Handler) RandomBet(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse
// @Router /bet [get]
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
bets, err := h.betSvc.GetAllBets(c.Context())
companyID := c.Locals("company_id").(domain.ValidInt64)
branchID := c.Locals("branch_id").(domain.ValidInt64)
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
BranchID: branchID,
CompanyID: companyID,
})
if err != nil {
h.logger.Error("Failed to get bets", "error", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets")

View File

@ -37,7 +37,7 @@ type CreateCashierReq struct {
func (h *Handler) CreateCashier(c *fiber.Ctx) error {
// Get user_id from middleware
companyID := c.Locals("company_id").(domain.ValidInt64)
// companyID := c.Locals("company_id").(domain.ValidInt64)
var req CreateCashierReq
if err := c.BodyParser(&req); err != nil {
@ -48,6 +48,13 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
// Cashiers inherit the company id from the branch id
branch, err := h.branchSvc.GetBranchByID(c.Context(), req.BranchID)
if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID is invalid", nil, nil)
}
userRequest := domain.CreateUserReq{
FirstName: req.FirstName,
LastName: req.LastName,
@ -56,7 +63,10 @@ func (h *Handler) CreateCashier(c *fiber.Ctx) error {
Password: req.Password,
Role: string(domain.RoleCashier),
Suspended: req.Suspended,
CompanyID: companyID,
CompanyID: domain.ValidInt64{
Value: branch.CompanyID,
Valid: true,
},
}
fmt.Print(req.Suspended)
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest, true)

View File

@ -225,35 +225,18 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
// @Router /transaction [get]
func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
// Get user_id from middleware
userID := c.Locals("user_id").(int64)
// Fetch user details
user, err := h.userSvc.GetUserByID(c.Context(), userID)
if err != nil {
h.logger.Error("Failed to fetch user details", "user_id", userID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve user details", err, nil)
}
// userID := c.Locals("user_id").(int64)
// role := c.Locals("role").(domain.Role)
companyID := c.Locals("company_id").(domain.ValidInt64)
branchID := c.Locals("branch_id").(domain.ValidInt64)
var transactions []domain.Transaction
// Check user role and fetch transactions accordingly
// TODO: filtering by the user role
switch user.Role {
case domain.RoleSuperAdmin:
// Admin can fetch all transactions
transactions, err = h.transactionSvc.GetAllTransactions(c.Context())
case domain.RoleAdmin:
// Admins can fetch transaction for company branches
transactions, err = h.transactionSvc.GetAllTransactions(c.Context())
case domain.RoleBranchManager, domain.RoleCashier:
// Branch Manager or Cashier can fetch transactions for their branches
// transactions, err = transactionSvc.GetTransactionByBranch(c.Context(), user.BranchID)
transactions, err = h.transactionSvc.GetAllTransactions(c.Context())
default:
// Unauthorized role
return response.WriteJSON(c, fiber.StatusForbidden, "Unauthorized", nil, nil)
}
transactions, err := h.transactionSvc.GetAllTransactions(c.Context(), domain.TransactionFilter{
CompanyID: companyID,
BranchID: branchID,
})
if err != nil {
h.logger.Error("Failed to get transactions", "error", err)

View File

@ -53,6 +53,22 @@ func (a *App) authMiddleware(c *fiber.Ctx) error {
c.Locals("company_id", claim.CompanyID)
c.Locals("refresh_token", refreshToken)
var branchID domain.ValidInt64
if claim.Role == domain.RoleCashier {
branch, err := a.branchSvc.GetBranchByCashier(c.Context(), claim.UserId)
if err != nil {
a.logger.Error("Failed to get branch id for bet", "error", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to branch id for bet")
}
branchID = domain.ValidInt64{
Value: branch.ID,
Valid: true,
}
}
c.Locals("branch_id", branchID)
return c.Next()
}

View File

@ -49,6 +49,7 @@ db-up:
.PHONY: db-down
db-down:
@docker volume rm fortunebet-backend_postgres_data
@docker compose down
postgres:
@docker exec -it fortunebet-backend-postgres-1 psql -U root -d gh