merge fixes and handler dependency injection

This commit is contained in:
Samuel Tariku 2025-04-23 07:46:08 +03:00
parent fa3b6a24d3
commit fcd926223a
20 changed files with 1328 additions and 1464 deletions

View File

@ -191,7 +191,7 @@ func (q *Queries) GetAllBranches(ctx context.Context) ([]BranchDetail, error) {
} }
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.suspended_at, users.suspended 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.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
` `
@ -219,6 +219,8 @@ func (q *Queries) GetAllCashiers(ctx context.Context) ([]User, error) {
&i.UpdatedAt, &i.UpdatedAt,
&i.SuspendedAt, &i.SuspendedAt,
&i.Suspended, &i.Suspended,
&i.ReferralCode,
&i.ReferredBy,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -428,7 +430,7 @@ func (q *Queries) GetBranchOperations(ctx context.Context, branchID int64) ([]Ge
} }
const GetCashiersByBranch = `-- name: GetCashiersByBranch :many 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.suspended_at, users.suspended 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.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
WHERE branch_cashiers.branch_id = $1 WHERE branch_cashiers.branch_id = $1
@ -457,6 +459,8 @@ func (q *Queries) GetCashiersByBranch(ctx context.Context, branchID int64) ([]Us
&i.UpdatedAt, &i.UpdatedAt,
&i.SuspendedAt, &i.SuspendedAt,
&i.Suspended, &i.Suspended,
&i.ReferralCode,
&i.ReferredBy,
); err != nil { ); err != nil {
return nil, err return nil, err
} }

View File

@ -33,8 +33,8 @@ func (e *Referralstatus) Scan(src interface{}) error {
} }
type NullReferralstatus struct { type NullReferralstatus struct {
Referralstatus Referralstatus Referralstatus Referralstatus `json:"referralstatus"`
Valid bool // Valid is true if Referralstatus is not NULL Valid bool `json:"valid"` // Valid is true if Referralstatus is not NULL
} }
// Scan implements the Scanner interface. // Scan implements the Scanner interface.
@ -223,7 +223,7 @@ type Odd struct {
} }
type Otp struct { type Otp struct {
ID int64 `json:"id"` ID int64 `json:"id"`
SentTo string `json:"sent_to"` SentTo string `json:"sent_to"`
Medium string `json:"medium"` Medium string `json:"medium"`
OtpFor string `json:"otp_for"` OtpFor string `json:"otp_for"`
@ -235,55 +235,29 @@ ID int64 `json:"id"`
} }
type Referral struct { type Referral struct {
ID int64 ID int64 `json:"id"`
ReferralCode string ReferralCode string `json:"referral_code"`
ReferrerID string ReferrerID string `json:"referrer_id"`
ReferredID pgtype.Text ReferredID pgtype.Text `json:"referred_id"`
Status Referralstatus Status Referralstatus `json:"status"`
RewardAmount pgtype.Numeric RewardAmount pgtype.Numeric `json:"reward_amount"`
CashbackAmount pgtype.Numeric CashbackAmount pgtype.Numeric `json:"cashback_amount"`
CreatedAt pgtype.Timestamptz CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ExpiresAt pgtype.Timestamptz ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
type ReferralSetting struct { type ReferralSetting struct {
ID int64 ID int64 `json:"id"`
ReferralRewardAmount pgtype.Numeric ReferralRewardAmount pgtype.Numeric `json:"referral_reward_amount"`
CashbackPercentage pgtype.Numeric CashbackPercentage pgtype.Numeric `json:"cashback_percentage"`
BetReferralBonusPercentage pgtype.Numeric BetReferralBonusPercentage pgtype.Numeric `json:"bet_referral_bonus_percentage"`
MaxReferrals int32 MaxReferrals int32 `json:"max_referrals"`
ExpiresAfterDays int32 ExpiresAfterDays int32 `json:"expires_after_days"`
UpdatedBy string UpdatedBy string `json:"updated_by"`
CreatedAt pgtype.Timestamptz CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Version int32 Version int32 `json:"version"`
}
type Referral struct {
ID int64
ReferralCode string
ReferrerID string
ReferredID pgtype.Text
Status Referralstatus
RewardAmount pgtype.Numeric
CashbackAmount pgtype.Numeric
CreatedAt pgtype.Timestamptz
UpdatedAt pgtype.Timestamptz
ExpiresAt pgtype.Timestamptz
}
type ReferralSetting struct {
ID int64
ReferralRewardAmount pgtype.Numeric
CashbackPercentage pgtype.Numeric
BetReferralBonusPercentage pgtype.Numeric
MaxReferrals int32
ExpiresAfterDays int32
UpdatedBy string
CreatedAt pgtype.Timestamptz
UpdatedAt pgtype.Timestamptz
Version int32
} }
type RefreshToken struct { type RefreshToken struct {
@ -369,48 +343,48 @@ type User struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
SuspendedAt pgtype.Timestamptz `json:"suspended_at"` SuspendedAt pgtype.Timestamptz `json:"suspended_at"`
Suspended bool `json:"suspended"` Suspended bool `json:"suspended"`
ReferralCode pgtype.Text ReferralCode pgtype.Text `json:"referral_code"`
ReferredBy pgtype.Text ReferredBy pgtype.Text `json:"referred_by"`
} }
type VirtualGameSession struct { type VirtualGameSession struct {
ID int64 ID int64 `json:"id"`
UserID int64 UserID int64 `json:"user_id"`
GameID string GameID string `json:"game_id"`
SessionToken string SessionToken string `json:"session_token"`
Currency string Currency string `json:"currency"`
Status string Status string `json:"status"`
CreatedAt pgtype.Timestamptz CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ExpiresAt pgtype.Timestamptz ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
type VirtualGameTransaction struct { type VirtualGameTransaction struct {
ID int64 ID int64 `json:"id"`
SessionID int64 SessionID int64 `json:"session_id"`
UserID int64 UserID int64 `json:"user_id"`
WalletID int64 WalletID int64 `json:"wallet_id"`
TransactionType string TransactionType string `json:"transaction_type"`
Amount int64 Amount int64 `json:"amount"`
Currency string Currency string `json:"currency"`
ExternalTransactionID string ExternalTransactionID string `json:"external_transaction_id"`
Status string Status string `json:"status"`
CreatedAt pgtype.Timestamptz CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz UpdatedAt pgtype.Timestamptz `json:"updated_at"`
} }
type Wallet struct { type Wallet struct {
ID int64 `json:"id"` ID int64 `json:"id"`
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
IsWithdraw bool `json:"is_withdraw"` IsWithdraw bool `json:"is_withdraw"`
IsBettable bool `json:"is_bettable"` IsBettable bool `json:"is_bettable"`
IsTransferable bool `json:"is_transferable"` IsTransferable bool `json:"is_transferable"`
UserID int64 `json:"user_id"` UserID int64 `json:"user_id"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
CreatedAt pgtype.Timestamp `json:"created_at"` CreatedAt pgtype.Timestamp `json:"created_at"`
UpdatedAt pgtype.Timestamp `json:"updated_at"` UpdatedAt pgtype.Timestamp `json:"updated_at"`
BonusBalance pgtype.Numeric BonusBalance pgtype.Numeric `json:"bonus_balance"`
CashBalance pgtype.Numeric CashBalance pgtype.Numeric `json:"cash_balance"`
} }
type WalletTransfer struct { type WalletTransfer struct {

View File

@ -24,11 +24,11 @@ INSERT INTO referrals (
` `
type CreateReferralParams struct { type CreateReferralParams struct {
ReferralCode string ReferralCode string `json:"referral_code"`
ReferrerID string ReferrerID string `json:"referrer_id"`
Status Referralstatus Status Referralstatus `json:"status"`
RewardAmount pgtype.Numeric RewardAmount pgtype.Numeric `json:"reward_amount"`
ExpiresAt pgtype.Timestamptz ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
func (q *Queries) CreateReferral(ctx context.Context, arg CreateReferralParams) (Referral, error) { func (q *Queries) CreateReferral(ctx context.Context, arg CreateReferralParams) (Referral, error) {
@ -69,12 +69,12 @@ INSERT INTO referral_settings (
` `
type CreateReferralSettingsParams struct { type CreateReferralSettingsParams struct {
ReferralRewardAmount pgtype.Numeric ReferralRewardAmount pgtype.Numeric `json:"referral_reward_amount"`
CashbackPercentage pgtype.Numeric CashbackPercentage pgtype.Numeric `json:"cashback_percentage"`
MaxReferrals int32 MaxReferrals int32 `json:"max_referrals"`
BetReferralBonusPercentage pgtype.Numeric BetReferralBonusPercentage pgtype.Numeric `json:"bet_referral_bonus_percentage"`
ExpiresAfterDays int32 ExpiresAfterDays int32 `json:"expires_after_days"`
UpdatedBy string UpdatedBy string `json:"updated_by"`
} }
func (q *Queries) CreateReferralSettings(ctx context.Context, arg CreateReferralSettingsParams) (ReferralSetting, error) { func (q *Queries) CreateReferralSettings(ctx context.Context, arg CreateReferralSettingsParams) (ReferralSetting, error) {
@ -182,10 +182,10 @@ WHERE referrer_id = $1
` `
type GetReferralStatsRow struct { type GetReferralStatsRow struct {
TotalReferrals int64 TotalReferrals int64 `json:"total_referrals"`
CompletedReferrals int64 CompletedReferrals int64 `json:"completed_referrals"`
TotalRewardEarned interface{} TotalRewardEarned interface{} `json:"total_reward_earned"`
PendingRewards interface{} PendingRewards interface{} `json:"pending_rewards"`
} }
func (q *Queries) GetReferralStats(ctx context.Context, referrerID string) (GetReferralStatsRow, error) { func (q *Queries) GetReferralStats(ctx context.Context, referrerID string) (GetReferralStatsRow, error) {
@ -211,9 +211,9 @@ RETURNING id, referral_code, referrer_id, referred_id, status, reward_amount, ca
` `
type UpdateReferralParams struct { type UpdateReferralParams struct {
ID int64 ID int64 `json:"id"`
ReferredID pgtype.Text ReferredID pgtype.Text `json:"referred_id"`
Status Referralstatus Status Referralstatus `json:"status"`
} }
func (q *Queries) UpdateReferral(ctx context.Context, arg UpdateReferralParams) (Referral, error) { func (q *Queries) UpdateReferral(ctx context.Context, arg UpdateReferralParams) (Referral, error) {
@ -243,8 +243,8 @@ WHERE id = $1
` `
type UpdateReferralCodeParams struct { type UpdateReferralCodeParams struct {
ID int64 ID int64 `json:"id"`
ReferralCode pgtype.Text ReferralCode pgtype.Text `json:"referral_code"`
} }
func (q *Queries) UpdateReferralCode(ctx context.Context, arg UpdateReferralCodeParams) error { func (q *Queries) UpdateReferralCode(ctx context.Context, arg UpdateReferralCodeParams) error {
@ -267,13 +267,13 @@ RETURNING id, referral_reward_amount, cashback_percentage, bet_referral_bonus_pe
` `
type UpdateReferralSettingsParams struct { type UpdateReferralSettingsParams struct {
ID int64 ID int64 `json:"id"`
ReferralRewardAmount pgtype.Numeric ReferralRewardAmount pgtype.Numeric `json:"referral_reward_amount"`
CashbackPercentage pgtype.Numeric CashbackPercentage pgtype.Numeric `json:"cashback_percentage"`
BetReferralBonusPercentage pgtype.Numeric BetReferralBonusPercentage pgtype.Numeric `json:"bet_referral_bonus_percentage"`
MaxReferrals int32 MaxReferrals int32 `json:"max_referrals"`
ExpiresAfterDays int32 ExpiresAfterDays int32 `json:"expires_after_days"`
UpdatedBy string UpdatedBy string `json:"updated_by"`
} }
func (q *Queries) UpdateReferralSettings(ctx context.Context, arg UpdateReferralSettingsParams) (ReferralSetting, error) { func (q *Queries) UpdateReferralSettings(ctx context.Context, arg UpdateReferralSettingsParams) (ReferralSetting, error) {

View File

@ -20,12 +20,12 @@ INSERT INTO virtual_game_sessions (
` `
type CreateVirtualGameSessionParams struct { type CreateVirtualGameSessionParams struct {
UserID int64 UserID int64 `json:"user_id"`
GameID string GameID string `json:"game_id"`
SessionToken string SessionToken string `json:"session_token"`
Currency string Currency string `json:"currency"`
Status string Status string `json:"status"`
ExpiresAt pgtype.Timestamptz ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
func (q *Queries) CreateVirtualGameSession(ctx context.Context, arg CreateVirtualGameSessionParams) (VirtualGameSession, error) { func (q *Queries) CreateVirtualGameSession(ctx context.Context, arg CreateVirtualGameSessionParams) (VirtualGameSession, error) {
@ -61,14 +61,14 @@ INSERT INTO virtual_game_transactions (
` `
type CreateVirtualGameTransactionParams struct { type CreateVirtualGameTransactionParams struct {
SessionID int64 SessionID int64 `json:"session_id"`
UserID int64 UserID int64 `json:"user_id"`
WalletID int64 WalletID int64 `json:"wallet_id"`
TransactionType string TransactionType string `json:"transaction_type"`
Amount int64 Amount int64 `json:"amount"`
Currency string Currency string `json:"currency"`
ExternalTransactionID string ExternalTransactionID string `json:"external_transaction_id"`
Status string Status string `json:"status"`
} }
func (q *Queries) CreateVirtualGameTransaction(ctx context.Context, arg CreateVirtualGameTransactionParams) (VirtualGameTransaction, error) { func (q *Queries) CreateVirtualGameTransaction(ctx context.Context, arg CreateVirtualGameTransactionParams) (VirtualGameTransaction, error) {
@ -154,8 +154,8 @@ WHERE id = $1
` `
type UpdateVirtualGameSessionStatusParams struct { type UpdateVirtualGameSessionStatusParams struct {
ID int64 ID int64 `json:"id"`
Status string Status string `json:"status"`
} }
func (q *Queries) UpdateVirtualGameSessionStatus(ctx context.Context, arg UpdateVirtualGameSessionStatusParams) error { func (q *Queries) UpdateVirtualGameSessionStatus(ctx context.Context, arg UpdateVirtualGameSessionStatusParams) error {
@ -170,8 +170,8 @@ WHERE id = $1
` `
type UpdateVirtualGameTransactionStatusParams struct { type UpdateVirtualGameTransactionStatusParams struct {
ID int64 ID int64 `json:"id"`
Status string Status string `json:"status"`
} }
func (q *Queries) UpdateVirtualGameTransactionStatus(ctx context.Context, arg UpdateVirtualGameTransactionStatusParams) error { func (q *Queries) UpdateVirtualGameTransactionStatus(ctx context.Context, arg UpdateVirtualGameTransactionStatusParams) error {

View File

@ -124,7 +124,7 @@ func (s *Service) ProcessReferral(ctx context.Context, referredPhone, referralCo
walletID := wallets[0].ID walletID := wallets[0].ID
currentBonus := float64(wallets[0].Balance) currentBonus := float64(wallets[0].Balance)
err = s.walletSvc.Add(ctx, walletID, domain.Currency(int64((currentBonus+referral.RewardAmount)*100))) err = s.walletSvc.AddToWallet(ctx, walletID, domain.Currency(int64((currentBonus+referral.RewardAmount)*100)))
if err != nil { if err != nil {
s.logger.Error("Failed to add referral reward to wallet", "walletID", walletID, "referrerID", referrerID, "error", err) s.logger.Error("Failed to add referral reward to wallet", "walletID", walletID, "referrerID", referrerID, "error", err)
return err return err
@ -162,7 +162,7 @@ func (s *Service) ProcessDepositBonus(ctx context.Context, userPhone string, amo
walletID := wallets[0].ID walletID := wallets[0].ID
bonus := amount * (settings.CashbackPercentage / 100) bonus := amount * (settings.CashbackPercentage / 100)
currentBonus := float64(wallets[0].Balance) currentBonus := float64(wallets[0].Balance)
err = s.walletSvc.Add(ctx, walletID, domain.Currency(int64((currentBonus+bonus)*100))) err = s.walletSvc.AddToWallet(ctx, walletID, domain.Currency(int64((currentBonus+bonus)*100)))
if err != nil { if err != nil {
s.logger.Error("Failed to add deposit bonus to wallet", "walletID", walletID, "userID", userID, "bonus", bonus, "error", err) s.logger.Error("Failed to add deposit bonus to wallet", "walletID", walletID, "userID", userID, "bonus", bonus, "error", err)
return err return err
@ -216,7 +216,7 @@ func (s *Service) ProcessBetReferral(ctx context.Context, userPhone string, betA
walletID := wallets[0].ID walletID := wallets[0].ID
currentBalance := float64(wallets[0].Balance) currentBalance := float64(wallets[0].Balance)
err = s.walletSvc.Add(ctx, walletID, domain.Currency(int64((currentBalance+bonus)*100))) err = s.walletSvc.AddToWallet(ctx, walletID, domain.Currency(int64((currentBalance+bonus)*100)))
if err != nil { if err != nil {
s.logger.Error("Failed to add bet referral bonus to wallet", "walletID", walletID, "referrerID", referrerID, "bonus", bonus, "error", err) s.logger.Error("Failed to add bet referral bonus to wallet", "walletID", walletID, "referrerID", referrerID, "bonus", bonus, "error", err)
return err return err

View File

@ -110,7 +110,7 @@ func (s *service) HandleCallback(ctx context.Context, callback *domain.PopOKCall
return errors.New("unknown transaction type") return errors.New("unknown transaction type")
} }
err = s.walletSvc.Add(ctx, walletID, domain.Currency(amount)) err = s.walletSvc.AddToWallet(ctx, walletID, domain.Currency(amount))
if err != nil { if err != nil {
s.logger.Error("Failed to update wallet", "walletID", walletID, "userID", session.UserID, "amount", amount, "error", err) s.logger.Error("Failed to update wallet", "walletID", walletID, "userID", session.UserID, "amount", amount, "error", err)
return err return err

View File

@ -107,7 +107,7 @@ func (h *Handler) RefreshToken(c *fiber.Ctx) error {
userId := c.Locals("user_id").(int64) userId := c.Locals("user_id").(int64)
role := c.Locals("role").(string) role := c.Locals("role").(string)
branchId := c.Locals("branch_id").(int64) branchId := c.Locals("branch_id").(int64)
err := authSvc.RefreshToken(c.Context(), req.RefreshToken) err := h.authSvc.RefreshToken(c.Context(), req.RefreshToken)
if err != nil { if err != nil {
h.logger.Info("Refresh token attempt failed", "refreshToken", req.RefreshToken, "error", err) h.logger.Info("Refresh token attempt failed", "refreshToken", req.RefreshToken, "error", err)
switch { switch {

View File

@ -2,14 +2,11 @@ package handlers
import ( import (
"encoding/json" "encoding/json"
"log/slog"
"strconv" "strconv"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -132,7 +129,7 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
} }
// Deduct a percentage of the amount // Deduct a percentage of the amount
// TODO move to service layer // TODO move to service layer. Make it fetch dynamically from company
var deductedAmount = req.Amount / 10 var deductedAmount = req.Amount / 10
err = h.walletSvc.DeductFromWallet(c.Context(), branch.WalletID, domain.ToCurrency(deductedAmount)) err = h.walletSvc.DeductFromWallet(c.Context(), branch.WalletID, domain.ToCurrency(deductedAmount))
@ -208,7 +205,7 @@ func (h *Handler) CreateBet(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
} }
odds, err := h.oddSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr) odds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr)
if err != nil { if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid market id", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid market id", err, nil)
@ -340,27 +337,25 @@ func (h *Handler) GetBetByID(c *fiber.Ctx) error {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /bet/cashout/{id} [get] // @Router /bet/cashout/{id} [get]
func GetBetByCashoutID(logger *slog.Logger, betSvc *bet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBetByCashoutID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { cashoutID := c.Params("id")
cashoutID := c.Params("id") // id, err := strconv.ParseInt(cashoutID, 10, 64)
// id, err := strconv.ParseInt(cashoutID, 10, 64)
// if err != nil { // if err != nil {
// logger.Error("Invalid cashout ID", "cashoutID", cashoutID, "error", err) // logger.Error("Invalid cashout ID", "cashoutID", cashoutID, "error", err)
// return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil) // return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, nil)
// } // }
bet, err := betSvc.GetBetByCashoutID(c.Context(), cashoutID)
if err != nil {
logger.Error("Failed to get bet by ID", "cashoutID", cashoutID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bet", err, nil)
}
res := convertBet(bet)
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
bet, err := h.betSvc.GetBetByCashoutID(c.Context(), cashoutID)
if err != nil {
h.logger.Error("Failed to get bet by ID", "cashoutID", cashoutID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bet", err, nil)
} }
res := convertBet(bet)
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
} }
type UpdateCashOutReq struct { type UpdateCashOutReq struct {

View File

@ -1,15 +1,10 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -102,76 +97,72 @@ func convertBranchDetail(branch domain.BranchDetail) BranchDetailRes {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch [post] // @Router /branch [post]
func CreateBranch(logger *slog.Logger, branchSvc *branch.Service, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateBranch(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { // Check if user is either branch manager / super main
// Check if user is either branch manager / super main // role := string(c.Locals("role").(domain.Role))
// role := string(c.Locals("role").(domain.Role))
// if role != string(domain.RoleAdmin) && role != string(domain.RoleSuperAdmin) && role != string(domain.RoleBranchManager) { // if role != string(domain.RoleAdmin) && role != string(domain.RoleSuperAdmin) && role != string(domain.RoleBranchManager) {
// logger.Error("Unauthorized access", "role", role) // logger.Error("Unauthorized access", "role", role)
// return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil) // return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
// } // }
var req CreateBranchReq var req CreateBranchReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
logger.Error("CreateBranchReq failed", "error", err) h.logger.Error("CreateBranchReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
} }
valErrs, ok := validator.Validate(c, req) valErrs, ok := h.validator.Validate(c, req)
if !ok { if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
// Create Branch Wallet // Create Branch Wallet
newWallet, err := walletSvc.CreateWallet(c.Context(), domain.CreateWallet{ newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false, IsWithdraw: false,
IsBettable: true, IsBettable: true,
IsTransferable: true, IsTransferable: true,
UserID: req.BranchManagerID, UserID: req.BranchManagerID,
})
if err != nil {
h.logger.Error("Create Branch Wallet failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create branch wallet", err, nil)
}
branch, err := h.branchSvc.CreateBranch(c.Context(), domain.CreateBranch{
Name: req.Name,
Location: req.Location,
WalletID: newWallet.ID,
BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID,
IsSelfOwned: req.IsSelfOwned,
})
if err != nil {
h.logger.Error("CreateBranchReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
}) })
}
if err != nil { for _, operation := range req.Operations {
logger.Error("Create Branch Wallet failed", "error", err) err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create branch wallet", err, nil) BranchID: branch.ID,
} OperationID: operation,
branch, err := branchSvc.CreateBranch(c.Context(), domain.CreateBranch{
Name: req.Name,
Location: req.Location,
WalletID: newWallet.ID,
BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID,
IsSelfOwned: req.IsSelfOwned,
}) })
if err != nil { if err != nil {
logger.Error("CreateBranchReq failed", "error", err) h.logger.Error("Failed to create branch operations", "BranchID", branch.ID, "operation", operation, "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error", "error": "Internal server error",
}) })
} }
for _, operation := range req.Operations {
err := branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
BranchID: branch.ID,
OperationID: operation,
})
if err != nil {
logger.Error("Failed to create branch operations", "BranchID", branch.ID, "operation", operation, "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
}
res := convertBranch(branch)
return response.WriteJSON(c, fiber.StatusCreated, "Branch Created", res, nil)
} }
res := convertBranch(branch)
return response.WriteJSON(c, fiber.StatusCreated, "Branch Created", res, nil)
} }
// CreateSupportedOperation godoc // CreateSupportedOperation godoc
@ -185,39 +176,36 @@ func CreateBranch(logger *slog.Logger, branchSvc *branch.Service, walletSvc *wal
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /supportedOperation [post] // @Router /supportedOperation [post]
func CreateSupportedOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateSupportedOperation(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req CreateSupportedOperationReq
var req CreateSupportedOperationReq
if err := c.BodyParser(&req); err != nil {
logger.Error("CreateSupportedOperationReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
operation, err := branchSvc.CreateSupportedOperation(c.Context(), domain.CreateSupportedOperation{
Name: req.Name,
Description: req.Description,
})
if err != nil {
logger.Error("CreateSupportedOperationReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := SupportedOperationRes{
Name: operation.Name,
Description: operation.Description,
}
return response.WriteJSON(c, fiber.StatusOK, "Operation Created", res, nil)
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateSupportedOperationReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
operation, err := h.branchSvc.CreateSupportedOperation(c.Context(), domain.CreateSupportedOperation{
Name: req.Name,
Description: req.Description,
})
if err != nil {
h.logger.Error("CreateSupportedOperationReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := SupportedOperationRes{
Name: operation.Name,
Description: operation.Description,
}
return response.WriteJSON(c, fiber.StatusOK, "Operation Created", res, nil)
} }
// CreateBranchOperation godoc // CreateBranchOperation godoc
@ -231,32 +219,29 @@ func CreateSupportedOperation(logger *slog.Logger, branchSvc *branch.Service, va
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /operation [post] // @Router /operation [post]
func CreateBranchOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateBranchOperation(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req CreateBranchOperationReq
var req CreateBranchOperationReq if err := c.BodyParser(&req); err != nil {
if err := c.BodyParser(&req); err != nil { h.logger.Error("CreateBranchOperationReq failed", "error", err)
logger.Error("CreateBranchOperationReq failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
err := branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
BranchID: req.BranchID,
OperationID: req.OperationID,
})
if err != nil {
logger.Error("CreateBranchOperationReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
BranchID: req.BranchID,
OperationID: req.OperationID,
})
if err != nil {
h.logger.Error("CreateBranchOperationReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil)
} }
// GetBranchByID godoc // GetBranchByID godoc
@ -270,27 +255,24 @@ func CreateBranchOperation(logger *slog.Logger, branchSvc *branch.Service, valid
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [get] // @Router /branch/{id} [get]
func GetBranchByID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBranchByID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64)
id, err := strconv.ParseInt(branchID, 10, 64) if err != nil {
if err != nil { h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
}
branch, err := branchSvc.GetBranchByID(c.Context(), id)
if err != nil {
logger.Error("Failed to get branch by ID", "branchID", id, "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)
} }
branch, err := h.branchSvc.GetBranchByID(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get branch by ID", "branchID", id, "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)
} }
// GetBranchByManagerID godoc // GetBranchByManagerID godoc
@ -304,29 +286,26 @@ func GetBranchByID(logger *slog.Logger, branchSvc *branch.Service, validator *cu
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /manager/{id}/branch [get] // @Router /manager/{id}/branch [get]
func GetBranchByManagerID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBranchByManagerID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { // TODO: Restrict any who isn't branch manager or higher
userID := c.Params("id")
// TODO: Restrict any who isn't branch manager or higher id, err := strconv.ParseInt(userID, 10, 64)
userID := c.Params("id") if err != nil {
id, err := strconv.ParseInt(userID, 10, 64) h.logger.Error("Invalid user ID", "userID", userID, "error", err)
if err != nil { return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", err, nil)
logger.Error("Invalid user ID", "userID", userID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", err, nil)
}
branches, err := branchSvc.GetBranchByManagerID(c.Context(), id)
if err != nil {
logger.Error("Failed to get branches", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
}
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Branch Manager retrieved", result, nil)
} }
branches, err := h.branchSvc.GetBranchByManagerID(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get branches", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
}
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Branch Manager retrieved", result, nil)
} }
// GetBranchByCompanyID godoc // GetBranchByCompanyID godoc
@ -340,27 +319,25 @@ func GetBranchByManagerID(logger *slog.Logger, branchSvc *branch.Service, valida
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company/{id}/branch [get] // @Router /company/{id}/branch [get]
func GetBranchByCompanyID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBranchByCompanyID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { companyID := c.Params("id")
companyID := c.Params("id") id, err := strconv.ParseInt(companyID, 10, 64)
id, err := strconv.ParseInt(companyID, 10, 64) if err != nil {
if err != nil { h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
logger.Error("Invalid company ID", "companyID", companyID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
}
branches, err := branchSvc.GetBranchByCompanyID(c.Context(), id)
if err != nil {
logger.Error("Failed to get branches", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
}
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
} }
branches, err := h.branchSvc.GetBranchByCompanyID(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get branches", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
}
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
} }
// GetAllBranches godoc // GetAllBranches godoc
@ -373,22 +350,19 @@ func GetBranchByCompanyID(logger *slog.Logger, branchSvc *branch.Service, valida
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch [get] // @Router /branch [get]
func GetAllBranches(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllBranches(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { // TODO: Limit the get all branches to only the companies for branch manager and cashiers
// TODO: Limit the get all branches to only the companies for branch manager and cashiers branches, err := h.branchSvc.GetAllBranches(c.Context())
branches, err := branchSvc.GetAllBranches(c.Context()) if err != nil {
if err != nil { h.logger.Error("Failed to get branches", "error", err)
logger.Error("Failed to get branches", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil)
}
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
} }
var result []BranchDetailRes = make([]BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
} }
// SearchBranch godoc // SearchBranch godoc
@ -402,29 +376,27 @@ func GetAllBranches(logger *slog.Logger, branchSvc *branch.Service, validator *c
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /search/branch [get] // @Router /search/branch [get]
func SearchBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) SearchBranch(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { // Get search query from request
// Get search query from request searchQuery := c.Query("q")
searchQuery := c.Query("q") if searchQuery == "" {
if searchQuery == "" { return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil)
}
// Call the service to search for branches
branches, err := branchSvc.SearchBranchByName(c.Context(), searchQuery)
if err != nil {
logger.Error("Failed to search branches", "query", searchQuery, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to search branches", err, nil)
}
// Convert branches to response format
var result []BranchDetailRes
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches retrieved successfully", result, nil)
} }
// Call the service to search for branches
branches, err := h.branchSvc.SearchBranchByName(c.Context(), searchQuery)
if err != nil {
h.logger.Error("Failed to search branches", "query", searchQuery, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to search branches", err, nil)
}
// Convert branches to response format
var result []BranchDetailRes
for _, branch := range branches {
result = append(result, convertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches retrieved successfully", result, nil)
} }
// GetAllSupportedOperations godoc // GetAllSupportedOperations godoc
@ -437,25 +409,23 @@ func SearchBranch(logger *slog.Logger, branchSvc *branch.Service, validator *cus
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /supportedOperation [get] // @Router /supportedOperation [get]
func GetAllSupportedOperations(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllSupportedOperations(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { operations, err := h.branchSvc.GetAllSupportedOperations(c.Context())
operations, err := branchSvc.GetAllSupportedOperations(c.Context()) if err != nil {
if err != nil { h.logger.Error("Failed to get operations", "error", err)
logger.Error("Failed to get operations", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get operations", err, nil)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get operations", err, nil)
}
var result []SupportedOperationRes = make([]SupportedOperationRes, 0, len(operations))
for _, operation := range operations {
result = append(result, SupportedOperationRes{
ID: operation.ID,
Name: operation.Name,
Description: operation.Description,
})
}
return response.WriteJSON(c, fiber.StatusOK, "SupportedOperations for Company retrieved", result, nil)
} }
var result []SupportedOperationRes = make([]SupportedOperationRes, 0, len(operations))
for _, operation := range operations {
result = append(result, SupportedOperationRes{
ID: operation.ID,
Name: operation.Name,
Description: operation.Description,
})
}
return response.WriteJSON(c, fiber.StatusOK, "SupportedOperations for Company retrieved", result, nil)
} }
// GetBranchOperations godoc // GetBranchOperations godoc
@ -469,34 +439,31 @@ func GetAllSupportedOperations(logger *slog.Logger, branchSvc *branch.Service, v
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/operation [get] // @Router /branch/{id}/operation [get]
func GetBranchOperations(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBranchOperations(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
branchID := c.Params("id") if err != nil {
id, err := strconv.ParseInt(branchID, 10, 64) h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
if err != nil { return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
}
operations, err := branchSvc.GetBranchOperations(c.Context(), id)
if err != nil {
logger.Error("Failed to get operation by ID", "branchID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve operation", err, nil)
}
var result []BranchOperationRes = make([]BranchOperationRes, 0, len(operations))
for _, branch := range operations {
result = append(result, BranchOperationRes{
Name: branch.OperationName,
Description: branch.OperationDescription,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operations retrieved successfully", result, nil)
} }
operations, err := h.branchSvc.GetBranchOperations(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get operation by ID", "branchID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve operation", err, nil)
}
var result []BranchOperationRes = make([]BranchOperationRes, 0, len(operations))
for _, branch := range operations {
result = append(result, BranchOperationRes{
Name: branch.OperationName,
Description: branch.OperationDescription,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operations retrieved successfully", result, nil)
} }
// GetBetByBranchID godoc // GetBetByBranchID godoc
@ -509,29 +476,27 @@ func GetBranchOperations(logger *slog.Logger, branchSvc *branch.Service, validat
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/bets [get] // @Router /branch/{id}/bets [get]
func GetBetByBranchID(logger *slog.Logger, betSvc *bet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetBetByBranchID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64)
id, err := strconv.ParseInt(branchID, 10, 64) if err != nil {
if err != nil { h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
}
bets, err := betSvc.GetBetByBranchID(c.Context(), id)
if err != nil {
logger.Error("Failed to get bets", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bets", err, nil)
}
var res []BetRes = make([]BetRes, 0, len(bets))
for _, bet := range bets {
res = append(res, convertBet(bet))
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Bets Retrieved", res, nil)
} }
bets, err := h.betSvc.GetBetByBranchID(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get bets", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bets", err, nil)
}
var res []BetRes = make([]BetRes, 0, len(bets))
for _, bet := range bets {
res = append(res, convertBet(bet))
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Bets Retrieved", res, nil)
} }
// UpdateBranch godoc // UpdateBranch godoc
@ -546,44 +511,42 @@ func GetBetByBranchID(logger *slog.Logger, betSvc *bet.Service, validator *custo
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [put] // @Router /branch/{id} [put]
func UpdateBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64)
id, err := strconv.ParseInt(branchID, 10, 64) if err != nil {
if err != nil { h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
}
var req CreateBranchReq
if err := c.BodyParser(&req); err != nil {
logger.Error("CreateBranchReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
branch, err := branchSvc.UpdateBranch(c.Context(), id, domain.UpdateBranch{
Name: req.Name,
Location: req.Location,
BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID,
IsSelfOwned: req.IsSelfOwned,
})
if err != nil {
logger.Error("Failed to update branch", "branchID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update branch", err, nil)
}
res := convertBranch(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch Updated", res, nil)
} }
var req CreateBranchReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateBranchReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
branch, err := h.branchSvc.UpdateBranch(c.Context(), id, domain.UpdateBranch{
Name: req.Name,
Location: req.Location,
BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID,
IsSelfOwned: req.IsSelfOwned,
})
if err != nil {
h.logger.Error("Failed to update branch", "branchID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update branch", err, nil)
}
res := convertBranch(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch Updated", res, nil)
} }
// DeleteBranch godoc // DeleteBranch godoc
@ -597,27 +560,23 @@ func UpdateBranch(logger *slog.Logger, branchSvc *branch.Service, validator *cus
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [delete] // @Router /branch/{id} [delete]
func DeleteBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) DeleteBranch(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
logger.Error("Invalid Branch ID", "branchID", branchID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil)
}
err = branchSvc.DeleteBranch(c.Context(), id)
if err != nil {
logger.Error("Failed to delete by ID", "Branch ID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Branch", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch removed successfully", nil, nil)
if err != nil {
h.logger.Error("Invalid Branch ID", "branchID", branchID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil)
} }
err = h.branchSvc.DeleteBranch(c.Context(), id)
if err != nil {
h.logger.Error("Failed to delete by ID", "Branch ID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Branch", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch removed successfully", nil, nil)
} }
// DeleteBranchOperation godoc // DeleteBranchOperation godoc
@ -632,33 +591,31 @@ func DeleteBranch(logger *slog.Logger, branchSvc *branch.Service, validator *cus
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/operation/{opID} [delete] // @Router /branch/{id}/operation/{opID} [delete]
func DeleteBranchOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) DeleteBranchOperation(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { branchID := c.Params("id")
branchID := c.Params("id") opID := c.Params("opID")
opID := c.Params("opID")
id, err := strconv.ParseInt(branchID, 10, 64) id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
logger.Error("Invalid Branch ID", "branchID", branchID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil)
}
operationID, err := strconv.ParseInt(opID, 10, 64)
if err != nil {
logger.Error("Invalid Operation ID", "operationID", opID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Operation ID", err, nil)
}
err = branchSvc.DeleteBranchOperation(c.Context(), id, operationID)
if err != nil {
logger.Error("Failed to delete operation", "Branch ID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Operation", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation removed successfully", nil, nil)
if err != nil {
h.logger.Error("Invalid Branch ID", "branchID", branchID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil)
} }
operationID, err := strconv.ParseInt(opID, 10, 64)
if err != nil {
h.logger.Error("Invalid Operation ID", "operationID", opID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Operation ID", err, nil)
}
err = h.branchSvc.DeleteBranchOperation(c.Context(), id, operationID)
if err != nil {
h.logger.Error("Failed to delete operation", "Branch ID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Operation", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation removed successfully", nil, nil)
} }

View File

@ -1,15 +1,11 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -34,39 +30,36 @@ type CreateCashierReq struct {
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /cashiers [post] // @Router /cashiers [post]
func CreateCashier(logger *slog.Logger, userSvc *user.Service, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateCashier(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req CreateCashierReq
if err := c.BodyParser(&req); err != nil {
var req CreateCashierReq h.logger.Error("RegisterUser failed", "error", err)
if err := c.BodyParser(&req); err != nil { return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
logger.Error("RegisterUser failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
userRequest := domain.CreateUserReq{
FirstName: req.FirstName,
LastName: req.LastName,
Email: req.Email,
PhoneNumber: req.PhoneNumber,
Password: req.Password,
Role: string(domain.RoleCashier),
}
newUser, err := userSvc.CreateUser(c.Context(), userRequest)
if err != nil {
logger.Error("CreateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
}
err = branchSvc.CreateBranchCashier(c.Context(), req.BranchID, newUser.ID)
if err != nil {
logger.Error("CreateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Cashier created successfully", nil, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
userRequest := domain.CreateUserReq{
FirstName: req.FirstName,
LastName: req.LastName,
Email: req.Email,
PhoneNumber: req.PhoneNumber,
Password: req.Password,
Role: string(domain.RoleCashier),
}
newUser, err := h.userSvc.CreateUser(c.Context(), userRequest)
if err != nil {
h.logger.Error("CreateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
}
err = h.branchSvc.CreateBranchCashier(c.Context(), req.BranchID, newUser.ID)
if err != nil {
h.logger.Error("CreateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Cashier created successfully", nil, nil)
} }
@ -98,51 +91,49 @@ type GetCashierRes struct {
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /cashiers [get] // @Router /cashiers [get]
func GetAllCashiers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllCashiers(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { // branchId := int64(12) //c.Locals("branch_id").(int64)
// branchId := int64(12) //c.Locals("branch_id").(int64) // filter := user.Filter{
// filter := user.Filter{ // Role: string(domain.RoleCashier),
// Role: string(domain.RoleCashier), // BranchId: user.ValidBranchId{
// BranchId: user.ValidBranchId{ // Value: branchId,
// Value: branchId, // Valid: true,
// Valid: true, // },
// }, // Page: c.QueryInt("page", 1),
// Page: c.QueryInt("page", 1), // PageSize: c.QueryInt("page_size", 10),
// PageSize: c.QueryInt("page_size", 10), // }
// } // valErrs, ok := validator.Validate(c, filter)
// valErrs, ok := validator.Validate(c, filter) // if !ok {
// if !ok { // return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
// return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) // }
// }
cashiers, err := userSvc.GetAllCashiers(c.Context()) cashiers, err := h.userSvc.GetAllCashiers(c.Context())
if err != nil { if err != nil {
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)
}
var result []GetCashierRes
for _, cashier := range cashiers {
result = append(result, GetCashierRes{
ID: cashier.ID,
FirstName: cashier.FirstName,
LastName: cashier.LastName,
Email: cashier.Email,
PhoneNumber: cashier.PhoneNumber,
Role: cashier.Role,
EmailVerified: cashier.EmailVerified,
PhoneVerified: cashier.PhoneVerified,
CreatedAt: cashier.CreatedAt,
UpdatedAt: cashier.UpdatedAt,
SuspendedAt: cashier.SuspendedAt,
Suspended: cashier.Suspended,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Cashiers retrieved successfully", result, nil)
} }
var result []GetCashierRes
for _, cashier := range cashiers {
result = append(result, GetCashierRes{
ID: cashier.ID,
FirstName: cashier.FirstName,
LastName: cashier.LastName,
Email: cashier.Email,
PhoneNumber: cashier.PhoneNumber,
Role: cashier.Role,
EmailVerified: cashier.EmailVerified,
PhoneVerified: cashier.PhoneVerified,
CreatedAt: cashier.CreatedAt,
UpdatedAt: cashier.UpdatedAt,
SuspendedAt: cashier.SuspendedAt,
Suspended: cashier.Suspended,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Cashiers retrieved successfully", result, nil)
} }
type updateUserReq struct { type updateUserReq struct {
@ -163,46 +154,44 @@ type updateUserReq struct {
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /cashiers/{id} [put] // @Router /cashiers/{id} [put]
func UpdateCashier(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) UpdateCashier(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req updateUserReq
var req updateUserReq if err := c.BodyParser(&req); err != nil {
if err := c.BodyParser(&req); err != nil { h.logger.Error("UpdateCashier failed", "error", err)
logger.Error("UpdateCashier failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
cashierIdStr := c.Params("id")
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
if err != nil {
logger.Error("UpdateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
}
err = userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserId: cashierId,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
Suspended: domain.ValidBool{
Value: req.Suspended,
Valid: true,
},
},
)
if err != nil {
logger.Error("UpdateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update cashier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Cashier updated successfully", nil, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
cashierIdStr := c.Params("id")
cashierId, err := strconv.ParseInt(cashierIdStr, 10, 64)
if err != nil {
h.logger.Error("UpdateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
}
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserId: cashierId,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
Suspended: domain.ValidBool{
Value: req.Suspended,
Valid: true,
},
},
)
if err != nil {
h.logger.Error("UpdateCashier failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update cashier", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Cashier updated successfully", nil, nil)
} }

View File

@ -1,14 +1,10 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -44,49 +40,46 @@ func convertCompany(company domain.Company) CompanyRes {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company [post] // @Router /company [post]
func CreateCompany(logger *slog.Logger, companySvc *company.Service, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateCompany(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req CreateCompanyReq
var req CreateCompanyReq if err := c.BodyParser(&req); err != nil {
if err := c.BodyParser(&req); err != nil { h.logger.Error("CreateCompanyReq failed", "error", err)
logger.Error("CreateCompanyReq failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
// Create Branch Wallet
newWallet, err := walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false,
IsBettable: true,
IsTransferable: true,
UserID: req.AdminID,
})
if err != nil {
logger.Error("Create Company Wallet failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create company wallet", err, nil)
}
company, err := companySvc.CreateCompany(c.Context(), domain.CreateCompany{
Name: req.Name,
AdminID: req.AdminID,
WalletID: newWallet.ID,
})
if err != nil {
logger.Error("CreateCompanyReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
// Create Branch Wallet
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false,
IsBettable: true,
IsTransferable: true,
UserID: req.AdminID,
})
if err != nil {
h.logger.Error("Create Company Wallet failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create company wallet", err, nil)
}
company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{
Name: req.Name,
AdminID: req.AdminID,
WalletID: newWallet.ID,
})
if err != nil {
h.logger.Error("CreateCompanyReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
} }
// GetAllCompanies godoc // GetAllCompanies godoc
@ -99,22 +92,22 @@ func CreateCompany(logger *slog.Logger, companySvc *company.Service, walletSvc *
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company [get] // @Router /company [get]
func GetAllCompanies(logger *slog.Logger, companySvc *company.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
companies, err := companySvc.GetAllCompanies(c.Context())
if err != nil {
logger.Error("Failed to get companies", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
}
var result []CompanyRes = make([]CompanyRes, 0, len(companies)) companies, err := h.companySvc.GetAllCompanies(c.Context())
if err != nil {
for _, company := range companies { h.logger.Error("Failed to get companies", "error", err)
result = append(result, convertCompany(company)) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
} }
var result []CompanyRes = make([]CompanyRes, 0, len(companies))
for _, company := range companies {
result = append(result, convertCompany(company))
}
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
} }
// GetCompanyByID godoc // GetCompanyByID godoc
@ -128,26 +121,26 @@ func GetAllCompanies(logger *slog.Logger, companySvc *company.Service, validator
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company/{id} [get] // @Router /company/{id} [get]
func GetCompanyByID(logger *slog.Logger, companySvc *company.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetCompanyByID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
companyID := c.Params("id")
id, err := strconv.ParseInt(companyID, 10, 64)
if err != nil {
logger.Error("Invalid company ID", "companyID", companyID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
}
company, err := companySvc.GetCompanyByID(c.Context(), id) companyID := c.Params("id")
id, err := strconv.ParseInt(companyID, 10, 64)
if err != nil { if err != nil {
logger.Error("Failed to get company by ID", "companyID", id, "error", err) h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
} }
company, err := h.companySvc.GetCompanyByID(c.Context(), id)
if err != nil {
h.logger.Error("Failed to get company by ID", "companyID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil)
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
} }
// UpdateCompany godoc // UpdateCompany godoc
@ -162,39 +155,39 @@ func GetCompanyByID(logger *slog.Logger, companySvc *company.Service, validator
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company/{id} [put] // @Router /company/{id} [put]
func UpdateCompany(logger *slog.Logger, companySvc *company.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) UpdateCompany(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
companyID := c.Params("id")
id, err := strconv.ParseInt(companyID, 10, 64)
if err != nil {
logger.Error("Invalid company ID", "companyID", companyID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
}
var req CreateCompanyReq companyID := c.Params("id")
if err := c.BodyParser(&req); err != nil { id, err := strconv.ParseInt(companyID, 10, 64)
logger.Error("CreateCompanyReq failed", "error", err) if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil) h.logger.Error("Invalid company ID", "companyID", companyID, "error", err)
} return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil)
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
company, err := companySvc.UpdateCompany(c.Context(), id, domain.UpdateCompany{
Name: req.Name,
AdminID: req.AdminID,
})
if err != nil {
logger.Error("Failed to update company", "companyID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", err, nil)
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil)
} }
var req CreateCompanyReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateCompanyReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
company, err := h.companySvc.UpdateCompany(c.Context(), id, domain.UpdateCompany{
Name: req.Name,
AdminID: req.AdminID,
})
if err != nil {
h.logger.Error("Failed to update company", "companyID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", err, nil)
}
res := convertCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil)
} }
// DeleteCompany godoc // DeleteCompany godoc
@ -208,22 +201,22 @@ func UpdateCompany(logger *slog.Logger, companySvc *company.Service, validator *
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /company/{id} [delete] // @Router /company/{id} [delete]
func DeleteCompany(logger *slog.Logger, companySvc *company.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) DeleteCompany(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
companyID := c.Params("id")
id, err := strconv.ParseInt(companyID, 10, 64)
if err != nil { companyID := c.Params("id")
logger.Error("Invalid Company ID", "companyID", companyID, "error", err) id, err := strconv.ParseInt(companyID, 10, 64)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Company ID", err, nil)
}
err = companySvc.DeleteCompany(c.Context(), id) if err != nil {
if err != nil { h.logger.Error("Invalid Company ID", "companyID", companyID, "error", err)
logger.Error("Failed to delete by ID", "Company ID", id, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Company ID", err, nil)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Company", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil)
} }
err = h.companySvc.DeleteCompany(c.Context(), id)
if err != nil {
h.logger.Error("Failed to delete by ID", "Company ID", id, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Company", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil)
} }

View File

@ -5,7 +5,11 @@ import (
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication" notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal" referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
@ -25,14 +29,34 @@ type Handler struct {
transactionSvc *transaction.Service transactionSvc *transaction.Service
ticketSvc *ticket.Service ticketSvc *ticket.Service
betSvc *bet.Service betSvc *bet.Service
branchSvc *branch.Service
companySvc *company.Service
prematchSvc *odds.ServiceImpl
eventSvc event.Service
virtualGameSvc virtualgameservice.VirtualGameService virtualGameSvc virtualgameservice.VirtualGameService
authSvc *authentication.Service authSvc *authentication.Service
jwtConfig jwtutil.JwtConfig jwtConfig jwtutil.JwtConfig
validator *customvalidator.CustomValidator validator *customvalidator.CustomValidator
} }
func New(logger *slog.Logger, notificationSvc notificationservice.NotificationStore, validator *customvalidator.CustomValidator, walletSvc *wallet.Service, func New(
referralSvc referralservice.ReferralStore, virtualGameSvc virtualgameservice.VirtualGameService, userSvc *user.Service, transactionSvc *transaction.Service, ticketSvc *ticket.Service, betSvc *bet.Service, authSvc *authentication.Service, jwtConfig jwtutil.JwtConfig) *Handler { logger *slog.Logger,
notificationSvc notificationservice.NotificationStore,
validator *customvalidator.CustomValidator,
walletSvc *wallet.Service,
referralSvc referralservice.ReferralStore,
virtualGameSvc virtualgameservice.VirtualGameService,
userSvc *user.Service,
transactionSvc *transaction.Service,
ticketSvc *ticket.Service,
betSvc *bet.Service,
authSvc *authentication.Service,
jwtConfig jwtutil.JwtConfig,
branchSvc *branch.Service,
companySvc *company.Service,
prematchSvc *odds.ServiceImpl,
eventSvc event.Service,
) *Handler {
return &Handler{ return &Handler{
logger: logger, logger: logger,
notificationSvc: notificationSvc, notificationSvc: notificationSvc,
@ -43,6 +67,10 @@ func New(logger *slog.Logger, notificationSvc notificationservice.NotificationSt
transactionSvc: transactionSvc, transactionSvc: transactionSvc,
ticketSvc: ticketSvc, ticketSvc: ticketSvc,
betSvc: betSvc, betSvc: betSvc,
branchSvc: branchSvc,
companySvc: companySvc,
prematchSvc: prematchSvc,
eventSvc: eventSvc,
virtualGameSvc: virtualGameSvc, virtualGameSvc: virtualGameSvc,
authSvc: authSvc, authSvc: authSvc,
jwtConfig: jwtConfig, jwtConfig: jwtConfig,

View File

@ -1,13 +1,11 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -31,32 +29,30 @@ type CreateManagerReq struct {
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /managers [post] // @Router /managers [post]
func CreateManager(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) CreateManager(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req CreateManagerReq
var req CreateManagerReq if err := c.BodyParser(&req); err != nil {
if err := c.BodyParser(&req); err != nil { h.logger.Error("RegisterUser failed", "error", err)
logger.Error("RegisterUser failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
user := domain.CreateUserReq{
FirstName: req.FirstName,
LastName: req.LastName,
Email: req.Email,
PhoneNumber: req.PhoneNumber,
Password: req.Password,
Role: string(domain.RoleBranchManager),
}
_, err := userSvc.CreateUser(c.Context(), user)
if err != nil {
logger.Error("CreateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers created successfully", nil, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
user := domain.CreateUserReq{
FirstName: req.FirstName,
LastName: req.LastName,
Email: req.Email,
PhoneNumber: req.PhoneNumber,
Password: req.Password,
Role: string(domain.RoleBranchManager),
}
_, err := h.userSvc.CreateUser(c.Context(), user)
if err != nil {
h.logger.Error("CreateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers created successfully", nil, nil)
} }
@ -73,29 +69,27 @@ func CreateManager(logger *slog.Logger, userSvc *user.Service, validator *custom
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /managers [get] // @Router /managers [get]
func GetAllManagers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { filter := user.Filter{
filter := user.Filter{ Role: string(domain.RoleBranchManager),
Role: string(domain.RoleBranchManager), BranchId: user.ValidBranchId{
BranchId: user.ValidBranchId{ Value: int64(c.QueryInt("branch_id")),
Value: int64(c.QueryInt("branch_id")), Valid: true,
Valid: true, },
}, Page: c.QueryInt("page", 1),
Page: c.QueryInt("page", 1), PageSize: c.QueryInt("page_size", 10),
PageSize: c.QueryInt("page_size", 10),
}
valErrs, ok := validator.Validate(c, filter)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
Managers, err := userSvc.GetAllUsers(c.Context(), filter)
if err != nil {
logger.Error("GetAllManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers retrieved successfully", Managers, nil)
} }
valErrs, ok := h.validator.Validate(c, filter)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
Managers, err := h.userSvc.GetAllUsers(c.Context(), filter)
if err != nil {
h.logger.Error("GetAllManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers retrieved successfully", Managers, nil)
} }
@ -111,46 +105,44 @@ func GetAllManagers(logger *slog.Logger, userSvc *user.Service, validator *custo
// @Failure 401 {object} response.APIResponse // @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /managers/{id} [put] // @Router /managers/{id} [put]
func UPdateManagers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) UpdateManagers(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error { var req updateUserReq
var req updateUserReq if err := c.BodyParser(&req); err != nil {
if err := c.BodyParser(&req); err != nil { h.logger.Error("UpdateManagers failed", "error", err)
logger.Error("UpdateManagers failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
ManagersIdStr := c.Params("id")
ManagersId, err := strconv.ParseInt(ManagersIdStr, 10, 64)
if err != nil {
logger.Error("UpdateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Managers ID", nil, nil)
}
err = userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserId: ManagersId,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
Suspended: domain.ValidBool{
Value: req.Suspended,
Valid: true,
},
},
)
if err != nil {
logger.Error("UpdateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers updated successfully", nil, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
ManagersIdStr := c.Params("id")
ManagersId, err := strconv.ParseInt(ManagersIdStr, 10, 64)
if err != nil {
h.logger.Error("UpdateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Managers ID", nil, nil)
}
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserId: ManagersId,
FirstName: domain.ValidString{
Value: req.FirstName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
Suspended: domain.ValidBool{
Value: req.Suspended,
Valid: true,
},
},
)
if err != nil {
h.logger.Error("UpdateManagers failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Managers", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Managers updated successfully", nil, nil)
} }

View File

@ -1,12 +1,9 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
"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"
) )
@ -22,20 +19,20 @@ import (
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/odds/{event_id} [get] // @Router /prematch/odds/{event_id} [get]
func GetPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler { func (h *Handler) GetPrematchOdds(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
eventID := c.Params("event_id")
if eventID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing event_id", nil, nil)
}
odds, err := prematchSvc.GetPrematchOdds(c.Context(), eventID) eventID := c.Params("event_id")
if err != nil { if eventID == "" {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve odds", nil, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Missing event_id", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
} }
odds, err := h.prematchSvc.GetPrematchOdds(c.Context(), eventID)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
} }
// GetALLPrematchOdds // GetALLPrematchOdds
@ -47,15 +44,15 @@ func GetPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.H
// @Success 200 {array} domain.Odd // @Success 200 {array} domain.Odd
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/odds [get] // @Router /prematch/odds [get]
func GetALLPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler { func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
odds, err := prematchSvc.GetALLPrematchOdds(c.Context())
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil) odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
} }
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
} }
// GetRawOddsByMarketID // GetRawOddsByMarketID
@ -70,26 +67,26 @@ func GetALLPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fibe
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/odds/upcoming/{upcoming_id}/market/{market_id} [get] // @Router /prematch/odds/upcoming/{upcoming_id}/market/{market_id} [get]
func GetRawOddsByMarketID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler { func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
marketID := c.Params("market_id")
upcomingID := c.Params("upcoming_id")
if marketID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
}
if upcomingID == "" { marketID := c.Params("market_id")
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil) upcomingID := c.Params("upcoming_id")
} if marketID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
rawOdds, err := prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil {
logger.Error("failed to fetch raw odds", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
} }
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil {
h.logger.Error("failed to fetch raw odds", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
} }
// @Summary Retrieve all upcoming events // @Summary Retrieve all upcoming events
@ -104,30 +101,30 @@ func GetRawOddsByMarketID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fi
// @Success 200 {array} domain.UpcomingEvent // @Success 200 {array} domain.UpcomingEvent
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/events [get] // @Router /prematch/events [get]
func GetAllUpcomingEvents(logger *slog.Logger, eventSvc event.Service) fiber.Handler { func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("page_size", 10)
leagueIDQuery := c.Query("league_id")
sportIDQuery := c.Query("sport_id")
leagueID := domain.ValidString{ page := c.QueryInt("page", 1)
Value: leagueIDQuery, pageSize := c.QueryInt("page_size", 10)
Valid: leagueIDQuery != "", leagueIDQuery := c.Query("league_id")
} sportIDQuery := c.Query("sport_id")
sportID := domain.ValidString{
Value: sportIDQuery,
Valid: sportIDQuery != "",
}
events, total, err := eventSvc.GetPaginatedUpcomingEvents(c.Context(), int32(pageSize), int32(page)-1, leagueID, sportID) leagueID := domain.ValidString{
Value: leagueIDQuery,
if err != nil { Valid: leagueIDQuery != "",
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
}
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil, page, int(total))
} }
sportID := domain.ValidString{
Value: sportIDQuery,
Valid: sportIDQuery != "",
}
events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(c.Context(), int32(pageSize), int32(page)-1, leagueID, sportID)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
}
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil, page, int(total))
} }
// @Summary Retrieve an upcoming by ID // @Summary Retrieve an upcoming by ID
@ -140,20 +137,20 @@ func GetAllUpcomingEvents(logger *slog.Logger, eventSvc event.Service) fiber.Han
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/events/{id} [get] // @Router /prematch/events/{id} [get]
func GetUpcomingEventByID(logger *slog.Logger, eventSvc event.Service) fiber.Handler { func (h *Handler) GetUpcomingEventByID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
id := c.Params("id")
if id == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
}
event, err := eventSvc.GetUpcomingEventByID(c.Context(), id) id := c.Params("id")
if err != nil { if id == "" {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
} }
event, err := h.eventSvc.GetUpcomingEventByID(c.Context(), id)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
} }
// @Summary Retrieve prematch odds by upcoming ID (FI) // @Summary Retrieve prematch odds by upcoming ID (FI)
@ -168,28 +165,28 @@ func GetUpcomingEventByID(logger *slog.Logger, eventSvc event.Service) fiber.Han
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /prematch/odds/upcoming/{upcoming_id} [get] // @Router /prematch/odds/upcoming/{upcoming_id} [get]
func GetPrematchOddsByUpcomingID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler { func (h *Handler) GetPrematchOddsByUpcomingID(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
upcomingID := c.Params("upcoming_id")
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10 upcomingID := c.Params("upcoming_id")
if err != nil || limit <= 0 { if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
if err != nil || offset < 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
}
odds, err := prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID, int32(limit), int32(offset))
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
} }
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
if err != nil || limit <= 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
}
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
if err != nil || offset < 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
}
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID, int32(limit), int32(offset))
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
} }

View File

@ -1,6 +1,7 @@
package handlers package handlers
import ( import (
"encoding/json"
"strconv" "strconv"
"time" "time"
@ -50,16 +51,6 @@ type TicketRes struct {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /ticket [post] // @Router /ticket [post]
func (h *Handler) CreateTicket(c *fiber.Ctx) error { func (h *Handler) CreateTicket(c *fiber.Ctx) error {
type CreateTicketReq struct {
Outcomes []int64 `json:"outcomes" validate:"required" example:"[1, 2, 3]"`
Amount float32 `json:"amount" validate:"required" example:"100.0"`
TotalOdds float32 `json:"total_odds" validate:"required" example:"4.22"`
}
type CreateTicketRes struct {
FastCode int64 `json:"fast_code" example:"1234"`
}
var req CreateTicketReq var req CreateTicketReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
h.logger.Error("Failed to parse CreateTicket request", "error", err) h.logger.Error("Failed to parse CreateTicket request", "error", err)
@ -70,106 +61,106 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
} }
// TODO Validate Outcomes Here and make sure they didn't expire // TODO Validate Outcomes Here and make sure they didn't expire
// Validation for creating tickets // Validation for creating tickets
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)
}
var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes))
for _, outcome := range req.Outcomes {
eventIDStr := strconv.FormatInt(outcome.EventID, 10)
marketIDStr := strconv.FormatInt(outcome.MarketID, 10)
oddIDStr := strconv.FormatInt(outcome.OddID, 10)
event, err := eventSvc.GetUpcomingEventByID(c.Context(), eventIDStr)
if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid event id", err, nil)
}
// Checking to make sure the event hasn't already started
currentTime := time.Now()
if event.StartTime.Before(currentTime) {
return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
}
odds, err := oddSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr)
if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid market id", err, nil)
}
type rawOddType struct {
ID string
Name string
Odds string
Header string
Handicap string
}
var selectedOdd rawOddType
var isOddFound bool = false
for _, raw := range odds.RawOdds {
var rawOdd rawOddType
rawBytes, err := json.Marshal(raw)
err = json.Unmarshal(rawBytes, &rawOdd)
if err != nil {
fmt.Println("Failed to unmarshal raw odd:", err)
continue
}
if rawOdd.ID == oddIDStr {
selectedOdd = rawOdd
isOddFound = true
}
}
if !isOddFound {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid odd id", nil, nil)
}
parsedOdd, err := strconv.ParseFloat(selectedOdd.Odds, 32)
outcomes = append(outcomes, domain.CreateTicketOutcome{
EventID: outcome.EventID,
OddID: outcome.OddID,
MarketID: outcome.MarketID,
HomeTeamName: event.HomeTeam,
AwayTeamName: event.AwayTeam,
MarketName: odds.MarketName,
Odd: float32(parsedOdd),
OddName: selectedOdd.Name,
OddHeader: selectedOdd.Header,
OddHandicap: selectedOdd.Handicap,
Expires: event.StartTime,
})
}
ticket, err := ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{
Amount: domain.ToCurrency(req.Amount),
TotalOdds: req.TotalOdds,
})
if err != nil {
logger.Error("CreateTicketReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
// Add the ticket id now that it has fetched from the database
for index := range outcomes {
outcomes[index].TicketID = ticket.ID
}
rows, err := ticketSvc.CreateTicketOutcome(c.Context(), outcomes)
if err != nil {
logger.Error("CreateTicketReq failed to create outcomes", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := CreateTicketRes{
FastCode: ticket.ID,
CreatedNumber: rows,
}
return response.WriteJSON(c, fiber.StatusOK, "Ticket Created", res, nil)
} }
var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes))
for _, outcome := range req.Outcomes {
eventIDStr := strconv.FormatInt(outcome.EventID, 10)
marketIDStr := strconv.FormatInt(outcome.MarketID, 10)
oddIDStr := strconv.FormatInt(outcome.OddID, 10)
event, err := h.eventSvc.GetUpcomingEventByID(c.Context(), eventIDStr)
if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid event id", err, nil)
}
// Checking to make sure the event hasn't already started
currentTime := time.Now()
if event.StartTime.Before(currentTime) {
return response.WriteJSON(c, fiber.StatusBadRequest, "The event has already expired", nil, nil)
}
odds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketIDStr, eventIDStr)
if err != nil {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid market id", err, nil)
}
type rawOddType struct {
ID string
Name string
Odds string
Header string
Handicap string
}
var selectedOdd rawOddType
var isOddFound bool = false
for _, raw := range odds.RawOdds {
var rawOdd rawOddType
rawBytes, err := json.Marshal(raw)
err = json.Unmarshal(rawBytes, &rawOdd)
if err != nil {
h.logger.Error("Failed to unmarshal raw odd:", err)
continue
}
if rawOdd.ID == oddIDStr {
selectedOdd = rawOdd
isOddFound = true
}
}
if !isOddFound {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid odd id", nil, nil)
}
parsedOdd, err := strconv.ParseFloat(selectedOdd.Odds, 32)
outcomes = append(outcomes, domain.CreateTicketOutcome{
EventID: outcome.EventID,
OddID: outcome.OddID,
MarketID: outcome.MarketID,
HomeTeamName: event.HomeTeam,
AwayTeamName: event.AwayTeam,
MarketName: odds.MarketName,
Odd: float32(parsedOdd),
OddName: selectedOdd.Name,
OddHeader: selectedOdd.Header,
OddHandicap: selectedOdd.Handicap,
Expires: event.StartTime,
})
}
ticket, err := h.ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{
Amount: domain.ToCurrency(req.Amount),
TotalOdds: req.TotalOdds,
})
if err != nil {
h.logger.Error("CreateTicketReq failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
// Add the ticket id now that it has fetched from the database
for index := range outcomes {
outcomes[index].TicketID = ticket.ID
}
rows, err := h.ticketSvc.CreateTicketOutcome(c.Context(), outcomes)
if err != nil {
h.logger.Error("CreateTicketReq failed to create outcomes", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
res := CreateTicketRes{
FastCode: ticket.ID,
CreatedNumber: rows,
}
return response.WriteJSON(c, fiber.StatusOK, "Ticket Created", res, nil)
} }
// GetTicketByID godoc // GetTicketByID godoc
@ -184,13 +175,6 @@ func (h *Handler) CreateTicket(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /ticket/{id} [get] // @Router /ticket/{id} [get]
func (h *Handler) GetTicketByID(c *fiber.Ctx) error { func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
type TicketRes struct {
ID int64 `json:"id" example:"1"`
Outcomes []domain.Outcome `json:"outcomes"`
Amount float32 `json:"amount" example:"100.0"`
TotalOdds float32 `json:"total_odds" example:"4.22"`
}
ticketID := c.Params("id") ticketID := c.Params("id")
id, err := strconv.ParseInt(ticketID, 10, 64) id, err := strconv.ParseInt(ticketID, 10, 64)
if err != nil { if err != nil {
@ -224,12 +208,6 @@ func (h *Handler) GetTicketByID(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /ticket [get] // @Router /ticket [get]
func (h *Handler) GetAllTickets(c *fiber.Ctx) error { func (h *Handler) GetAllTickets(c *fiber.Ctx) error {
type TicketRes struct {
ID int64 `json:"id" example:"1"`
Outcomes []domain.Outcome `json:"outcomes"`
Amount float32 `json:"amount" example:"100.0"`
TotalOdds float32 `json:"total_odds" example:"4.22"`
}
tickets, err := h.ticketSvc.GetAllTickets(c.Context()) tickets, err := h.ticketSvc.GetAllTickets(c.Context())
if err != nil { if err != nil {

View File

@ -73,75 +73,74 @@ func convertTransaction(transaction domain.Transaction) TransactionRes {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /transaction [post] // @Router /transaction [post]
func (h *Handler) CreateTransaction(c *fiber.Ctx) error { func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
userID := c.Locals("user_id").(int64) userID := c.Locals("user_id").(int64)
user, err := userSvc.GetUserByID(c.Context(), userID) user, err := h.userSvc.GetUserByID(c.Context(), userID)
if user.Role == domain.RoleCustomer { if user.Role == domain.RoleCustomer {
logger.Error("CreateTransactionReq failed") h.logger.Error("CreateTransactionReq failed")
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"error": "unauthorized access", "error": "unauthorized access",
})
}
// TODO: Add validation to make sure that the bet hasn't already been cashed out by someone else
var branchID int64
if user.Role == domain.RoleAdmin || user.Role == domain.RoleBranchManager || user.Role == domain.RoleSuperAdmin {
branch, err := branchSvc.GetBranchByID(c.Context(), 1)
if err != nil {
logger.Error("CreateTransactionReq no branches")
return response.WriteJSON(c, fiber.StatusBadRequest, "This user type doesn't have branches", err, nil)
}
branchID = branch.ID
} else {
branch, err := branchSvc.GetBranchByCashier(c.Context(), user.ID)
if err != nil {
logger.Error("CreateTransactionReq failed, branch id invalid")
return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil)
}
branchID = branch.ID
}
var req CreateTransactionReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateTransaction failed to parse request", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
logger.Error("CreateTransactionReq failed v", "error", valErrs)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transaction, err := transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{
BranchID: branchID,
CashierID: userID,
Amount: domain.ToCurrency(req.Amount),
BetID: req.BetID,
Type: domain.TransactionType(req.Type),
PaymentOption: domain.PaymentOption(req.PaymentOption),
FullName: req.FullName,
PhoneNumber: req.PhoneNumber,
BankCode: req.BankCode,
BeneficiaryName: req.BeneficiaryName,
AccountName: req.AccountName,
AccountNumber: req.AccountNumber,
ReferenceNumber: req.ReferenceNumber,
}) })
}
// TODO: Add validation to make sure that the bet hasn't already been cashed out by someone else
var branchID int64
if user.Role == domain.RoleAdmin || user.Role == domain.RoleBranchManager || user.Role == domain.RoleSuperAdmin {
branch, err := h.branchSvc.GetBranchByID(c.Context(), 1)
if err != nil { if err != nil {
logger.Error("CreateTransactionReq failed", "error", err) h.logger.Error("CreateTransactionReq no branches")
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "This user type doesn't have branches", err, nil)
} }
err = betSvc.UpdateCashOut(c.Context(), req.BetID, true) branchID = branch.ID
} else {
branch, err := h.branchSvc.GetBranchByCashier(c.Context(), user.ID)
if err != nil { if err != nil {
logger.Error("CreateTransactionReq failed", "error", err) h.logger.Error("CreateTransactionReq failed, branch id invalid")
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Branch ID invalid", err, nil)
} }
branchID = branch.ID
}
var req CreateTransactionReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateTransaction failed to parse request", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
h.logger.Error("CreateTransactionReq failed v", "error", valErrs)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transaction, err := h.transactionSvc.CreateTransaction(c.Context(), domain.CreateTransaction{
BranchID: branchID,
CashierID: userID,
Amount: domain.ToCurrency(req.Amount),
BetID: req.BetID,
Type: domain.TransactionType(req.Type),
PaymentOption: domain.PaymentOption(req.PaymentOption),
FullName: req.FullName,
PhoneNumber: req.PhoneNumber,
BankCode: req.BankCode,
BeneficiaryName: req.BeneficiaryName,
AccountName: req.AccountName,
AccountNumber: req.AccountNumber,
ReferenceNumber: req.ReferenceNumber,
})
if err != nil {
h.logger.Error("CreateTransactionReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
}
err = h.betSvc.UpdateCashOut(c.Context(), req.BetID, true)
if err != nil {
h.logger.Error("CreateTransactionReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil)
} }
res := convertTransaction(transaction) res := convertTransaction(transaction)
@ -159,47 +158,49 @@ func (h *Handler) CreateTransaction(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /transaction [get] // @Router /transaction [get]
func (h *Handler) GetAllTransactions(c *fiber.Ctx) error { func (h *Handler) GetAllTransactions(c *fiber.Ctx) error {
// Get user_id from middleware // Get user_id from middleware
userID := c.Locals("user_id").(int64) userID := c.Locals("user_id").(int64)
// Fetch user details // Fetch user details
user, err := userSvc.GetUserByID(c.Context(), userID) user, err := h.userSvc.GetUserByID(c.Context(), userID)
if err != nil { if err != nil {
logger.Error("Failed to fetch user details", "user_id", userID, "error", err) 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) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve user details", err, nil)
} }
var transactions []domain.Transaction var transactions []domain.Transaction
// Check user role and fetch transactions accordingly // Check user role and fetch transactions accordingly
switch user.Role { // TODO: filtering by the user role
case domain.RoleSuperAdmin: switch user.Role {
// Admin can fetch all transactions case domain.RoleSuperAdmin:
transactions, err = transactionSvc.GetAllTransactions(c.Context()) // Admin can fetch all transactions
case domain.RoleAdmin: transactions, err = h.transactionSvc.GetAllTransactions(c.Context())
// Admin can fetch all transactions case domain.RoleAdmin:
transactions, err = transactionSvc.GetAllTransactions(c.Context()) // Admins can fetch transaction for company branches
case domain.RoleBranchManager, domain.RoleCashier:
// Branch Manager or Cashier can fetch transactions for their branch
// transactions, err = transactionSvc.GetTransactionByBranch(c.Context(), user.BranchID)
transactions, err = transactionSvc.GetAllTransactions(c.Context())
default:
// Unauthorized role
return response.WriteJSON(c, fiber.StatusForbidden, "Unauthorized", nil, nil)
}
if err != nil { transactions, err = h.transactionSvc.GetAllTransactions(c.Context())
logger.Error("Failed to get transactions", "error", err) case domain.RoleBranchManager, domain.RoleCashier:
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transactions", err, nil) // 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)
}
if err != nil {
h.logger.Error("Failed to get transactions", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transactions", err, nil)
}
res := make([]TransactionRes, len(transactions)) res := make([]TransactionRes, len(transactions))
for i, transaction := range transactions { for i, transaction := range transactions {
res[i] = convertTransaction(transaction) res[i] = convertTransaction(transaction)
} }
return response.WriteJSON(c, fiber.StatusOK, "Transactions retrieved successfully", res, nil) return response.WriteJSON(c, fiber.StatusOK, "Transactions retrieved successfully", res, nil)
}
} }
// GetTransactionByID godoc // GetTransactionByID godoc
@ -255,11 +256,11 @@ func (h *Handler) UpdateTransactionVerified(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID") return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction ID")
} }
var req UpdateTransactionVerifiedReq var req UpdateTransactionVerifiedReq
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
logger.Error("Failed to parse UpdateTransactionVerified request", "error", err) h.logger.Error("Failed to parse UpdateTransactionVerified request", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
} }
if valErrs, ok := h.validator.Validate(c, req); !ok { if valErrs, ok := h.validator.Validate(c, req); !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)

View File

@ -1,15 +1,11 @@
package handlers package handlers
import ( import (
"log/slog"
"strconv" "strconv"
"time" "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -83,30 +79,30 @@ type CreateRefillReq struct {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /transfer/wallet/{id} [get] // @Router /transfer/wallet/{id} [get]
func GetTransfersByWallet(logger *slog.Logger, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetTransfersByWallet(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
walletID := c.Params("id")
id, err := strconv.ParseInt(walletID, 10, 64) walletID := c.Params("id")
if err != nil { id, err := strconv.ParseInt(walletID, 10, 64)
logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
}
transfers, err := walletSvc.GetTransfersByWallet(c.Context(), int64(id)) if err != nil {
if err != nil { h.logger.Error("Invalid wallet ID", "walletID", walletID, "error", err)
logger.Error("Failed to get transfers by wallet", "walletID", walletID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transfers", err, nil)
}
var transferResponses []TransferWalletRes
for _, transfer := range transfers {
transferResponses = append(transferResponses, convertTransfer(transfer))
}
return response.WriteJSON(c, fiber.StatusOK, "Transfers retrieved successfully", transferResponses, nil)
} }
transfers, err := h.walletSvc.GetTransfersByWallet(c.Context(), int64(id))
if err != nil {
h.logger.Error("Failed to get transfers by wallet", "walletID", walletID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve transfers", err, nil)
}
var transferResponses []TransferWalletRes
for _, transfer := range transfers {
transferResponses = append(transferResponses, convertTransfer(transfer))
}
return response.WriteJSON(c, fiber.StatusOK, "Transfers retrieved successfully", transferResponses, nil)
} }
// TransferToWallet godoc // TransferToWallet godoc
@ -120,63 +116,61 @@ func GetTransfersByWallet(logger *slog.Logger, walletSvc *wallet.Service, valida
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /transfer/wallet/:id [post] // @Router /transfer/wallet/:id [post]
func TransferToWallet(logger *slog.Logger, walletSvc *wallet.Service, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) TransferToWallet(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
receiverIDString := c.Params("id") receiverIDString := c.Params("id")
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64) receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
if err != nil {
logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
}
// Get sender ID from the cashier
userID := c.Locals("user_id").(int64)
role := string(c.Locals("role").(domain.Role))
var senderID int64
if role == string(domain.RoleCustomer) {
logger.Error("Unauthorized access", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
} else if role == string(domain.RoleBranchManager) || role == string(domain.RoleAdmin) || role == string(domain.RoleSuperAdmin) {
// TODO Add a way for admins to reference branch wallet
senderID = 0
logger.Error("Will", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusBadRequest, "Unauthorized access", nil, nil)
} else {
cashierBranch, err := branchSvc.GetBranchByCashier(c.Context(), userID)
if err != nil {
logger.Error("Failed to get branch", "user ID", userID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve cashier branch", err, nil)
}
senderID = cashierBranch.WalletID
}
var req CreateTransferReq
if err := c.BodyParser(&req); err != nil {
logger.Error("CreateTransferReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transfer, err := walletSvc.TransferToWallet(c.Context(), senderID, receiverID, domain.ToCurrency(req.Amount), domain.PaymentMethod(req.PaymentMethod), domain.ValidInt64{Value: userID, Valid: true})
if !ok {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Transfer Failed", err, nil)
}
res := convertTransfer(transfer)
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
if err != nil {
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
} }
// Get sender ID from the cashier
userID := c.Locals("user_id").(int64)
role := string(c.Locals("role").(domain.Role))
var senderID int64
if role == string(domain.RoleCustomer) {
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
} else if role == string(domain.RoleBranchManager) || role == string(domain.RoleAdmin) || role == string(domain.RoleSuperAdmin) {
// TODO Add a way for admins to reference branch wallet
senderID = 0
h.logger.Error("Will", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusBadRequest, "Unauthorized access", nil, nil)
} else {
cashierBranch, err := h.branchSvc.GetBranchByCashier(c.Context(), userID)
if err != nil {
h.logger.Error("Failed to get branch", "user ID", userID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve cashier branch", err, nil)
}
senderID = cashierBranch.WalletID
}
var req CreateTransferReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateTransferReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transfer, err := h.walletSvc.TransferToWallet(c.Context(), senderID, receiverID, domain.ToCurrency(req.Amount), domain.PaymentMethod(req.PaymentMethod), domain.ValidInt64{Value: userID, Valid: true})
if !ok {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Transfer Failed", err, nil)
}
res := convertTransfer(transfer)
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
} }
// RefillWallet godoc // RefillWallet godoc
@ -190,56 +184,54 @@ func TransferToWallet(logger *slog.Logger, walletSvc *wallet.Service, branchSvc
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /transfer/refill/:id [post] // @Router /transfer/refill/:id [post]
func RefillWallet(logger *slog.Logger, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) RefillWallet(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
receiverIDString := c.Params("id") receiverIDString := c.Params("id")
receiverID, err := strconv.ParseInt(receiverIDString, 10, 64) receiverID, err := strconv.ParseInt(receiverIDString, 10, 64)
if err != nil {
logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
}
// Get sender ID from the cashier
userID := c.Locals("user_id").(int64)
role := string(c.Locals("role").(domain.Role))
if role != string(domain.RoleSuperAdmin) {
logger.Error("Unauthorized access", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
}
var req CreateRefillReq
if err := c.BodyParser(&req); err != nil {
logger.Error("CreateRefillReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transfer, err := walletSvc.RefillWallet(c.Context(), domain.CreateTransfer{
Amount: domain.ToCurrency(req.Amount),
PaymentMethod: domain.TRANSFER_BANK,
ReceiverWalletID: receiverID,
CashierID: domain.ValidInt64{
Value: userID,
Valid: true,
},
Type: domain.TransferType("deposit"),
})
if !ok {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Creating Transfer Failed", err, nil)
}
res := convertTransfer(transfer)
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
if err != nil {
h.logger.Error("Invalid wallet ID", "walletID", receiverID, "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid wallet ID", err, nil)
} }
// Get sender ID from the cashier
userID := c.Locals("user_id").(int64)
role := string(c.Locals("role").(domain.Role))
if role != string(domain.RoleSuperAdmin) {
h.logger.Error("Unauthorized access", "userID", userID, "role", role)
return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
}
var req CreateRefillReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateRefillReq failed", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil)
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
}
transfer, err := h.walletSvc.RefillWallet(c.Context(), domain.CreateTransfer{
Amount: domain.ToCurrency(req.Amount),
PaymentMethod: domain.TRANSFER_BANK,
ReceiverWalletID: receiverID,
CashierID: domain.ValidInt64{
Value: userID,
Valid: true,
},
Type: domain.TransferType("deposit"),
})
if !ok {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Creating Transfer Failed", err, nil)
}
res := convertTransfer(transfer)
return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil)
} }

View File

@ -290,6 +290,21 @@ func (h *Handler) ResetPassword(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil) return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
} }
type UserProfileRes struct {
ID int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
PhoneNumber string `json:"phone_number"`
Role domain.Role `json:"role"`
EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"`
}
// UserProfile godoc // UserProfile godoc
// @Summary Get user profile // @Summary Get user profile
// @Description Get user profile // @Description Get user profile
@ -302,20 +317,6 @@ func (h *Handler) ResetPassword(c *fiber.Ctx) error {
// @Security Bearer // @Security Bearer
// @Router /user/profile [get] // @Router /user/profile [get]
func (h *Handler) UserProfile(c *fiber.Ctx) error { func (h *Handler) UserProfile(c *fiber.Ctx) error {
type UserProfileRes struct {
ID int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
PhoneNumber string `json:"phone_number"`
Role domain.Role `json:"role"`
EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
SuspendedAt time.Time `json:"suspended_at"`
Suspended bool `json:"suspended"`
}
userID, ok := c.Locals("user_id").(int64) userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 { if !ok || userID == 0 {
@ -372,45 +373,43 @@ type SearchUserByNameOrPhoneReq struct {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /user/search [post] // @Router /user/search [post]
func SearchUserByNameOrPhone(logger *slog.Logger, userSvc *user.Service, func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
validator *customvalidator.CustomValidator) fiber.Handler { var req SearchUserByNameOrPhoneReq
return func(c *fiber.Ctx) error { if err := c.BodyParser(&req); err != nil {
var req SearchUserByNameOrPhoneReq h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
logger.Error("SearchUserByNameOrPhone failed", "error", err) "error": "Invalid request",
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ })
"error": "Invalid request",
})
}
valErrs, ok := validator.Validate(c, req)
if !ok {
response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
return nil
}
users, err := userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString)
if err != nil {
logger.Error("SearchUserByNameOrPhone failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
for _, user := range users {
res = append(res, UserProfileRes{
ID: user.ID,
FirstName: user.FirstName,
LastName: user.LastName,
Email: user.Email,
PhoneNumber: user.PhoneNumber,
Role: user.Role,
EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
SuspendedAt: user.SuspendedAt,
Suspended: user.Suspended,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Search Successful", res, nil)
} }
valErrs, ok := h.validator.Validate(c, req)
if !ok {
response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
return nil
}
users, err := h.userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString)
if err != nil {
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Internal server error",
})
}
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
for _, user := range users {
res = append(res, UserProfileRes{
ID: user.ID,
FirstName: user.FirstName,
LastName: user.LastName,
Email: user.Email,
PhoneNumber: user.PhoneNumber,
Role: user.Role,
EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
SuspendedAt: user.SuspendedAt,
Suspended: user.Suspended,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Search Successful", res, nil)
} }

View File

@ -88,17 +88,6 @@ type BranchWalletRes struct {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /wallet/{id} [get] // @Router /wallet/{id} [get]
func (h *Handler) GetWalletByID(c *fiber.Ctx) error { func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
type WalletRes struct {
ID int64 `json:"id" example:"1"`
Balance float32 `json:"amount" example:"100.0"`
IsWithdraw bool `json:"is_withdraw" example:"true"`
IsBettable bool `json:"is_bettable" example:"true"`
IsActive bool `json:"is_active" example:"true"`
UserID int64 `json:"user_id" example:"1"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
walletID := c.Params("id") walletID := c.Params("id")
id, err := strconv.ParseInt(walletID, 10, 64) id, err := strconv.ParseInt(walletID, 10, 64)
if err != nil { if err != nil {
@ -112,7 +101,7 @@ func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet") return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet")
} }
res := convertWallet(wallet) res := convertWallet(wallet)
return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil) return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil)
} }
@ -127,24 +116,23 @@ func (h *Handler) GetWalletByID(c *fiber.Ctx) error {
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /wallet [get] // @Router /wallet [get]
func GetAllWallets(logger *slog.Logger, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllWallets(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
wallets, err := walletSvc.GetAllWallets(c.Context()) wallets, err := h.walletSvc.GetAllWallets(c.Context())
if err != nil { if err != nil {
logger.Error("Failed to get wallets", "error", err) h.logger.Error("Failed to get wallets", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
}
var res []WalletRes = make([]WalletRes, 0, len(wallets))
for _, wallet := range wallets {
res = append(res, convertWallet(wallet))
}
return response.WriteJSON(c, fiber.StatusOK, "All Wallets retrieved", res, nil)
} }
var res []WalletRes = make([]WalletRes, 0, len(wallets))
for _, wallet := range wallets {
res = append(res, convertWallet(wallet))
}
return response.WriteJSON(c, fiber.StatusOK, "All wallets retrieved successfully", res, nil)
} }
// GetAllBranchWallets godoc // GetAllBranchWallets godoc
@ -157,38 +145,34 @@ func GetAllWallets(logger *slog.Logger, walletSvc *wallet.Service, validator *cu
// @Failure 400 {object} response.APIResponse // @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /branchWallet [get] // @Router /branchWallet [get]
func GetAllBranchWallets(logger *slog.Logger, walletSvc *wallet.Service, validator *customvalidator.CustomValidator) fiber.Handler { func (h *Handler) GetAllBranchWallets(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
wallets, err := walletSvc.GetAllBranchWallets(c.Context()) wallets, err := h.walletSvc.GetAllBranchWallets(c.Context())
if err != nil { if err != nil {
logger.Error("Failed to get wallets", "error", err) h.logger.Error("Failed to get wallets", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve wallets", err, nil)
}
var res []BranchWalletRes = make([]BranchWalletRes, 0, len(wallets))
for _, wallet := range wallets {
res = append(res, BranchWalletRes{
ID: wallet.ID,
Balance: wallet.Balance.Float64(),
IsActive: wallet.IsActive,
Name: wallet.Name,
Location: wallet.Location,
BranchManagerID: wallet.BranchManagerID,
CompanyID: wallet.CompanyID,
IsSelfOwned: wallet.IsSelfOwned,
UpdatedAt: wallet.UpdatedAt,
CreatedAt: wallet.CreatedAt,
})
}
return response.WriteJSON(c, fiber.StatusOK, "All Wallets retrieved", res, nil)
} }
}
return response.WriteJSON(c, fiber.StatusOK, "All wallets retrieved successfully", res, nil) var res []BranchWalletRes = make([]BranchWalletRes, 0, len(wallets))
for _, wallet := range wallets {
res = append(res, BranchWalletRes{
ID: wallet.ID,
Balance: wallet.Balance.Float64(),
IsActive: wallet.IsActive,
Name: wallet.Name,
Location: wallet.Location,
BranchManagerID: wallet.BranchManagerID,
CompanyID: wallet.CompanyID,
IsSelfOwned: wallet.IsSelfOwned,
UpdatedAt: wallet.UpdatedAt,
CreatedAt: wallet.CreatedAt,
})
}
return response.WriteJSON(c, fiber.StatusOK, "All Wallets retrieved", res, nil)
} }
// UpdateWalletActive godoc // UpdateWalletActive godoc
@ -247,18 +231,6 @@ func (h *Handler) UpdateWalletActive(c *fiber.Ctx) error {
// @Failure 500 {object} response.APIResponse // @Failure 500 {object} response.APIResponse
// @Router /user/wallet [get] // @Router /user/wallet [get]
func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error { func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
type CustomerWalletRes struct {
ID int64 `json:"id" example:"1"`
RegularID int64 `json:"regular_id" example:"1"`
RegularBalance float32 `json:"regular_balance" example:"100.0"`
StaticID int64 `json:"static_id" example:"1"`
StaticBalance float32 `json:"static_balance" example:"100.0"`
CustomerID int64 `json:"customer_id" example:"1"`
CompanyID int64 `json:"company_id" example:"1"`
RegularUpdatedAt time.Time `json:"regular_updated_at"`
StaticUpdatedAt time.Time `json:"static_updated_at"`
CreatedAt time.Time `json:"created_at"`
}
userID, ok := c.Locals("user_id").(int64) userID, ok := c.Locals("user_id").(int64)
if !ok || userID == 0 { if !ok || userID == 0 {
@ -291,18 +263,7 @@ func (h *Handler) GetCustomerWallet(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet") return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve wallet")
} }
res := CustomerWalletRes{ res := convertCustomerWallet(wallet)
ID: wallet.ID,
RegularID: wallet.RegularID,
RegularBalance: wallet.RegularBalance.Float64(),
StaticID: wallet.StaticID,
StaticBalance: wallet.StaticBalance.Float64(),
CustomerID: wallet.CustomerID,
CompanyID: wallet.CompanyID,
RegularUpdatedAt: wallet.RegularUpdatedAt,
StaticUpdatedAt: wallet.StaticUpdatedAt,
CreatedAt: wallet.CreatedAt,
}
return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil) return response.WriteJSON(c, fiber.StatusOK, "Wallet retrieved successfully", res, nil)
} }

View File

@ -25,6 +25,10 @@ func (a *App) initAppRoutes() {
a.betSvc, a.betSvc,
a.authSvc, a.authSvc,
a.JwtConfig, a.JwtConfig,
a.branchSvc,
a.companySvc,
a.prematchSvc,
a.eventSvc,
) )
// Auth Routes // Auth Routes
@ -66,7 +70,7 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/user/profile", a.authMiddleware, h.UserProfile) a.fiber.Get("/user/profile", a.authMiddleware, h.UserProfile)
a.fiber.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet) a.fiber.Get("/user/wallet", a.authMiddleware, h.GetCustomerWallet)
a.fiber.Post("/user/search", a.authMiddleware, handlers.SearchUserByNameOrPhone(a.logger, a.userSvc, a.validator)) a.fiber.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)
// Referral Routes // Referral Routes
a.fiber.Post("/referral/create", a.authMiddleware, h.CreateReferralCode) a.fiber.Post("/referral/create", a.authMiddleware, h.CreateReferralCode)
@ -74,53 +78,53 @@ func (a *App) initAppRoutes() {
a.fiber.Get("/referral/settings", h.GetReferralSettings) a.fiber.Get("/referral/settings", h.GetReferralSettings)
a.fiber.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings) a.fiber.Patch("/referral/settings", a.authMiddleware, h.UpdateReferralSettings)
a.fiber.Get("/cashiers", a.authMiddleware, handlers.GetAllCashiers(a.logger, a.userSvc, a.validator)) a.fiber.Get("/cashiers", a.authMiddleware, h.GetAllCashiers)
a.fiber.Post("/cashiers", a.authMiddleware, handlers.CreateCashier(a.logger, a.userSvc, a.branchSvc, a.validator)) a.fiber.Post("/cashiers", a.authMiddleware, h.CreateCashier)
a.fiber.Put("/cashiers/:id", a.authMiddleware, handlers.UpdateCashier(a.logger, a.userSvc, a.validator)) a.fiber.Put("/cashiers/:id", a.authMiddleware, h.UpdateCashier)
// //
a.fiber.Get("/managers", a.authMiddleware, handlers.GetAllManagers(a.logger, a.userSvc, a.validator)) a.fiber.Get("/managers", a.authMiddleware, h.GetAllManagers)
a.fiber.Post("/managers", a.authMiddleware, handlers.CreateManager(a.logger, a.userSvc, a.validator)) a.fiber.Post("/managers", a.authMiddleware, h.CreateManager)
a.fiber.Put("/managers/:id", a.authMiddleware, handlers.UPdateManagers(a.logger, a.userSvc, a.validator)) a.fiber.Put("/managers/:id", a.authMiddleware, h.UpdateManagers)
a.fiber.Get("/manager/:id/branch", a.authMiddleware, handlers.GetBranchByManagerID(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/manager/:id/branch", a.authMiddleware, h.GetBranchByManagerID)
a.fiber.Get("/company/:id/branch", a.authMiddleware, handlers.GetBranchByCompanyID(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/company/:id/branch", a.authMiddleware, h.GetBranchByCompanyID)
a.fiber.Get("/prematch/odds/:event_id", handlers.GetPrematchOdds(a.logger, a.prematchSvc)) a.fiber.Get("/prematch/odds/:event_id", h.GetPrematchOdds)
a.fiber.Get("/prematch/odds", handlers.GetALLPrematchOdds(a.logger, a.prematchSvc)) a.fiber.Get("/prematch/odds", h.GetALLPrematchOdds)
a.fiber.Get("/prematch/odds/upcoming/:upcoming_id/market/:market_id", handlers.GetRawOddsByMarketID(a.logger, a.prematchSvc)) a.fiber.Get("/prematch/odds/upcoming/:upcoming_id/market/:market_id", h.GetRawOddsByMarketID)
a.fiber.Get("/prematch/events/:id", handlers.GetUpcomingEventByID(a.logger, a.eventSvc)) a.fiber.Get("/prematch/events/:id", h.GetUpcomingEventByID)
a.fiber.Get("/prematch/events", handlers.GetAllUpcomingEvents(a.logger, a.eventSvc)) a.fiber.Get("/prematch/events", h.GetAllUpcomingEvents)
a.fiber.Get("/prematch/odds/upcoming/:upcoming_id", handlers.GetPrematchOddsByUpcomingID(a.logger, a.prematchSvc)) a.fiber.Get("/prematch/odds/upcoming/:upcoming_id", h.GetPrematchOddsByUpcomingID)
// Swagger // Swagger
a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler()) a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())
// Branch // Branch
a.fiber.Post("/branch", a.authMiddleware, handlers.CreateBranch(a.logger, a.branchSvc, a.walletSvc, a.validator)) a.fiber.Post("/branch", a.authMiddleware, h.CreateBranch)
a.fiber.Get("/branch", a.authMiddleware, handlers.GetAllBranches(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/branch", a.authMiddleware, h.GetAllBranches)
a.fiber.Get("/branch/:id", a.authMiddleware, handlers.GetBranchByID(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/branch/:id", a.authMiddleware, h.GetBranchByID)
a.fiber.Get("/branch/:id/bets", a.authMiddleware, handlers.GetBetByBranchID(a.logger, a.betSvc, a.validator)) a.fiber.Get("/branch/:id/bets", a.authMiddleware, h.GetBetByBranchID)
a.fiber.Put("/branch/:id", a.authMiddleware, handlers.UpdateBranch(a.logger, a.branchSvc, a.validator)) a.fiber.Put("/branch/:id", a.authMiddleware, h.UpdateBranch)
a.fiber.Delete("/branch/:id", a.authMiddleware, handlers.DeleteBranch(a.logger, a.branchSvc, a.validator)) a.fiber.Delete("/branch/:id", a.authMiddleware, h.DeleteBranch)
a.fiber.Get("/search/branch", a.authMiddleware, handlers.SearchBranch(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/search/branch", a.authMiddleware, h.SearchBranch)
// /branch/search // /branch/search
// branch/wallet // branch/wallet
// Branch Operation // Branch Operation
a.fiber.Get("/supportedOperation", a.authMiddleware, handlers.GetAllSupportedOperations(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/supportedOperation", a.authMiddleware, h.GetAllSupportedOperations)
a.fiber.Post("/supportedOperation", a.authMiddleware, handlers.CreateSupportedOperation(a.logger, a.branchSvc, a.validator)) a.fiber.Post("/supportedOperation", a.authMiddleware, h.CreateSupportedOperation)
a.fiber.Post("/operation", a.authMiddleware, handlers.CreateBranchOperation(a.logger, a.branchSvc, a.validator)) a.fiber.Post("/operation", a.authMiddleware, h.CreateBranchOperation)
a.fiber.Get("/branch/:id/operation", a.authMiddleware, handlers.GetBranchOperations(a.logger, a.branchSvc, a.validator)) a.fiber.Get("/branch/:id/operation", a.authMiddleware, h.GetBranchOperations)
a.fiber.Delete("/branch/:id/operation/:opID", a.authMiddleware, handlers.DeleteBranchOperation(a.logger, a.branchSvc, a.validator)) a.fiber.Delete("/branch/:id/operation/:opID", a.authMiddleware, h.DeleteBranchOperation)
// Company // Company
a.fiber.Post("/company", a.authMiddleware, a.SuperAdminOnly, handlers.CreateCompany(a.logger, a.companySvc, a.walletSvc, a.validator)) a.fiber.Post("/company", a.authMiddleware, a.SuperAdminOnly, h.CreateCompany)
a.fiber.Get("/company", a.authMiddleware, a.SuperAdminOnly, handlers.GetAllCompanies(a.logger, a.companySvc, a.validator)) a.fiber.Get("/company", a.authMiddleware, a.SuperAdminOnly, h.GetAllCompanies)
a.fiber.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, handlers.GetCompanyByID(a.logger, a.companySvc, a.validator)) a.fiber.Get("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.GetCompanyByID)
a.fiber.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, handlers.UpdateCompany(a.logger, a.companySvc, a.validator)) a.fiber.Put("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateCompany)
a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, handlers.DeleteCompany(a.logger, a.companySvc, a.validator)) a.fiber.Delete("/company/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteCompany)
// Ticket Routes // Ticket Routes
a.fiber.Post("/ticket", h.CreateTicket) a.fiber.Post("/ticket", h.CreateTicket)
@ -131,21 +135,21 @@ func (a *App) initAppRoutes() {
a.fiber.Post("/bet", h.CreateBet) a.fiber.Post("/bet", h.CreateBet)
a.fiber.Get("/bet", h.GetAllBet) a.fiber.Get("/bet", h.GetAllBet)
a.fiber.Get("/bet/:id", h.GetBetByID) a.fiber.Get("/bet/:id", h.GetBetByID)
a.fiber.Get("/bet/cashout/:id", a.authMiddleware, handlers.GetBetByCashoutID(a.logger, a.betSvc, a.validator)) a.fiber.Get("/bet/cashout/:id", a.authMiddleware, h.GetBetByCashoutID)
a.fiber.Patch("/bet/:id", h.UpdateCashOut) a.fiber.Patch("/bet/:id", h.UpdateCashOut)
a.fiber.Delete("/bet/:id", h.DeleteBet) a.fiber.Delete("/bet/:id", h.DeleteBet)
// Wallet // Wallet
a.fiber.Get("/wallet", handlers.GetAllWallets(a.logger, a.walletSvc, a.validator)) a.fiber.Get("/wallet", h.GetAllWallets)
a.fiber.Get("/wallet/:id", handlers.GetWalletByID(a.logger, a.walletSvc, a.validator)) a.fiber.Get("/wallet/:id", h.GetWalletByID)
a.fiber.Put("/wallet/:id", handlers.UpdateWalletActive(a.logger, a.walletSvc, a.validator)) a.fiber.Put("/wallet/:id", h.UpdateWalletActive)
a.fiber.Get("/branchWallet", a.authMiddleware, handlers.GetAllBranchWallets(a.logger, a.walletSvc, a.validator)) a.fiber.Get("/branchWallet", a.authMiddleware, h.GetAllBranchWallets)
// Transfer // Transfer
// /transfer/wallet - transfer from one wallet to another wallet // /transfer/wallet - transfer from one wallet to another wallet
a.fiber.Post("/transfer/wallet/:id", a.authMiddleware, handlers.TransferToWallet(a.logger, a.walletSvc, a.branchSvc, a.validator)) a.fiber.Post("/transfer/wallet/:id", a.authMiddleware, h.TransferToWallet)
a.fiber.Get("/transfer/wallet/:id", a.authMiddleware, handlers.GetTransfersByWallet(a.logger, a.walletSvc, a.validator)) a.fiber.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, handlers.RefillWallet(a.logger, a.walletSvc, a.validator)) a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
// Transactions /transactions // Transactions /transactions
a.fiber.Post("/transaction", h.CreateTransaction) a.fiber.Post("/transaction", h.CreateTransaction)