Yimaru-BackEnd/internal/web_server/handlers/bet_handler.go

760 lines
24 KiB
Go

package handlers
import (
"fmt"
"strconv"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
// CreateBet godoc
// @Summary Create a bet
// @Description Creates a bet
// @Tags bet
// @Accept json
// @Produce json
// @Param createBet body domain.CreateBetReq true "Creates bet"
// @Success 200 {object} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet [post]
func (h *Handler) CreateBet(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
userID := c.Locals("user_id").(int64)
role := c.Locals("role").(domain.Role)
var req domain.CreateBetReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Error("Failed to parse CreateBet request",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
}
res, err := h.CreateBetInternal(c, req, userID, role, companyID.Value)
if err != nil {
h.mongoLoggerSvc.Error("Failed to create bet",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("user_id", userID),
zap.String("role", string(role)),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create bet:"+err.Error())
}
h.mongoLoggerSvc.Info("Bet created successfully",
zap.Int("status_code", fiber.StatusOK),
zap.Int64("user_id", userID),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", res, nil)
}
// CreateBetWithFastCode godoc
// @Summary Create a bet with fast code
// @Description Creates a bet with fast code
// @Tags bet
// @Accept json
// @Produce json
// @Param createBetWithFastCode body domain.CreateBetWithFastCodeReq true "Creates bet"
// @Success 200 {object} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet/fastcode [post]
func (h *Handler) CreateBetWithFastCode(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
userID := c.Locals("user_id").(int64)
role := c.Locals("role").(domain.Role)
var req domain.CreateBetWithFastCodeReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Error("Failed to parse CreateBet request",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
}
bet, err := h.betSvc.GetBetByFastCode(c.Context(), req.FastCode)
if err != nil {
h.mongoLoggerSvc.Info("failed to get bet with fast code",
zap.String("fast_code", req.FastCode),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "failed to get bet with fast code:"+err.Error())
}
if bet.UserID == userID {
h.mongoLoggerSvc.Info("User cannot refer himself",
zap.Int64("bet_id", bet.ID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
zap.Error(err),
)
return fiber.NewError(fiber.StatusBadRequest, "User cannot use his own referral code")
}
outcomes, err := h.betSvc.GetBetOutcomeByBetID(c.Context(), bet.ID)
if err != nil {
h.mongoLoggerSvc.Info("failed to get BetOutcomes by BetID",
zap.Int64("bet_id", bet.ID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
zap.Error(err),
)
return fiber.NewError(fiber.StatusBadRequest, "failed to get BetOutcomes by BetID:"+err.Error())
}
bet_outcomes := []domain.CreateBetOutcomeReq{}
for _, outcome := range outcomes {
bet_outcomes = append(bet_outcomes, domain.CreateBetOutcomeReq{
EventID: outcome.EventID,
OddID: outcome.OddID,
MarketID: outcome.MarketID,
})
}
// This can be for both online and offline bets
// If bet is an online bet (if the customer role creates the bet on their own)
// then the branchID is null
newReq := domain.CreateBetReq{
Amount: req.Amount,
Outcomes: bet_outcomes,
BranchID: req.BranchID,
}
res, err := h.CreateBetInternal(c, newReq, userID, role, companyID.Value)
if err != nil {
h.mongoLoggerSvc.Error("Failed to create bet",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("user_id", userID),
zap.String("role", string(role)),
zap.Any("newReq", newReq),
zap.Time("timestamp", time.Now()),
zap.Error(err),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create bet:"+err.Error())
}
wallet, _ := h.walletSvc.GetCustomerWallet(c.Context(), bet.UserID)
// amount added for fast code owner can be fetched from settings in db
settingList, err := h.settingSvc.GetOverrideSettingsList(c.Context(), companyID.Value)
amount := settingList.AmountForBetReferral
_, err = h.walletSvc.AddToWallet(c.Context(), wallet.StaticID, amount, domain.ValidInt64{},
domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Added %v to static wallet by referring using fast_code", amount.Float32()))
if err != nil {
h.mongoLoggerSvc.Error("Failed to add reward to static bet",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Int64("user_id", userID),
zap.Float32("amount", amount.Float32()),
zap.Int64("static wallet_id", wallet.StaticID),
zap.Time("timestamp", time.Now()),
zap.Error(err),
)
return fiber.NewError(fiber.StatusBadRequest, "Failed to add reward to static bet:"+err.Error())
}
h.mongoLoggerSvc.Info("Bet created successfully",
zap.Int("status_code", fiber.StatusOK),
zap.Int64("user_id", userID),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", res, nil)
}
func (h *Handler) CreateBetInternal(c *fiber.Ctx, req domain.CreateBetReq, userID int64, role domain.Role, companyID int64) (domain.CreateBetRes, error) {
valErrs, ok := h.validator.Validate(c, req)
if !ok {
h.mongoLoggerSvc.Error("CreateBet validation failed",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Any("validation_errors", valErrs),
zap.Time("timestamp", time.Now()),
)
return domain.CreateBetRes{}, fmt.Errorf("%s", valErrs)
}
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role, companyID)
if err != nil {
switch err {
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, wallet.ErrBalanceInsufficient:
h.mongoLoggerSvc.Info("PlaceBet failed",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Int64("userID", userID),
zap.Int64("companyID", companyID),
zap.String("role", string(role)),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return domain.CreateBetRes{}, err
}
h.mongoLoggerSvc.Error("PlaceBet failed",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Int64("userID", userID),
zap.Int64("companyID", companyID),
zap.String("role", string(role)),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return domain.CreateBetRes{}, err
}
return res, nil
}
// RandomBet godoc
// @Summary Generate a random bet
// @Description Generate a random bet
// @Tags bet
// @Accept json
// @Produce json
// @Param createBet body domain.RandomBetReq true "Create Random bet"
// @Success 200 {object} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/random/bet [post]
func (h *Handler) RandomBet(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
userID := c.Locals("user_id").(int64)
leagueIDQuery, err := strconv.ParseInt(c.Query("league_id"), 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("invalid league id",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "invalid league id")
}
sportIDQuery, err := strconv.Atoi(c.Query("sport_id"))
if err != nil {
h.mongoLoggerSvc.Info("invalid sport id",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "invalid sport id")
}
firstStartTimeQuery := c.Query("first_start_time")
lastStartTimeQuery := c.Query("last_start_time")
leagueID := domain.ValidInt64{
Value: leagueIDQuery,
Valid: leagueIDQuery != 0,
}
sportID := domain.ValidInt32{
Value: int32(sportIDQuery),
Valid: sportIDQuery != 0,
}
var firstStartTime domain.ValidTime
if firstStartTimeQuery != "" {
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid first_start_time format",
zap.String("first_start_time", firstStartTimeQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid first_start_time format")
}
firstStartTime = domain.ValidTime{
Value: firstStartTimeParsed,
Valid: true,
}
}
var lastStartTime domain.ValidTime
if lastStartTimeQuery != "" {
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid last_start_time format",
zap.String("last_start_time", lastStartTimeQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid last_start_time format")
}
lastStartTime = domain.ValidTime{
Value: lastStartTimeParsed,
Valid: true,
}
}
var req domain.RandomBetReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Info("Failed to parse RandomBet request",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.mongoLoggerSvc.Error("RandomBet validation failed",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Any("validation_errors", valErrs),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
var res domain.CreateBetRes
for i := 0; i < int(req.NumberOfBets); i++ {
res, err = h.betSvc.PlaceRandomBet(c.Context(), userID, req.BranchID, companyID.Value, leagueID, sportID, firstStartTime, lastStartTime)
if err != nil {
switch err {
case bet.ErrNoEventsAvailable:
return fiber.NewError(fiber.StatusNotFound, "No events found")
}
h.mongoLoggerSvc.Error("Random Bet failed place random bet",
zap.Int64("userID", userID),
zap.Int64("branch_id", req.BranchID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet:"+err.Error())
}
}
h.mongoLoggerSvc.Info("Random bet(s) created successfully",
zap.Int("status_code", fiber.StatusOK),
zap.Int64("user_id", userID),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", res, nil)
}
// GetAllBet godoc
// @Summary Gets all bets
// @Description Gets all the bets
// @Tags bet
// @Accept json
// @Produce json
// @Success 200 {array} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet [get]
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
role := c.Locals("role").(domain.Role)
// companyID := c.Locals("company_id").(domain.ValidInt64)
// branchID := c.Locals("branch_id").(domain.ValidInt64)
var isShopBet domain.ValidBool
isShopBetQuery := c.Query("is_shop")
if isShopBetQuery != "" && role == domain.RoleSuperAdmin {
isShopBetParse, err := strconv.ParseBool(isShopBetQuery)
if err != nil {
h.mongoLoggerSvc.Info("failed to parse is_shop_bet",
zap.Int("status_code", fiber.StatusBadRequest),
zap.String("is_shop", isShopBetQuery),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "failed to parse is_shop_bet")
}
isShopBet = domain.ValidBool{
Value: isShopBetParse,
Valid: true,
}
}
searchQuery := c.Query("query")
searchString := domain.ValidString{
Value: searchQuery,
Valid: searchQuery != "",
}
createdBeforeQuery := c.Query("created_before")
var createdBefore domain.ValidTime
if createdBeforeQuery != "" {
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid created_before format",
zap.String("time", createdBeforeQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
}
createdBefore = domain.ValidTime{
Value: createdBeforeParsed,
Valid: true,
}
}
createdAfterQuery := c.Query("created_after")
var createdAfter domain.ValidTime
if createdAfterQuery != "" {
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid created_after format",
zap.String("created_after", createdAfterQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
}
createdAfter = domain.ValidTime{
Value: createdAfterParsed,
Valid: true,
}
}
bets, err := h.betSvc.GetAllBets(c.Context(), domain.BetFilter{
CompanyID: companyID,
IsShopBet: isShopBet,
Query: searchString,
CreatedBefore: createdBefore,
CreatedAfter: createdAfter,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to get all bets",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets፡"+err.Error())
}
res := make([]domain.BetRes, len(bets))
for i, bet := range bets {
res[i] = domain.ConvertBet(bet)
}
return response.WriteJSON(c, fiber.StatusOK, "All bets retrieved successfully", res, nil)
}
// GetBetByID godoc
// @Summary Gets bet by id
// @Description Gets a single bet by id
// @Tags bet
// @Accept json
// @Produce json
// @Param id path int true "Bet ID"
// @Success 200 {object} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [get]
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
betID := c.Params("id")
id, err := strconv.ParseInt(betID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid bet ID",
zap.String("betID", betID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
}
bet, err := h.betSvc.GetBetByID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get bet by ID",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
if bet.CompanyID != companyID.Value {
h.mongoLoggerSvc.Warn("User Attempt to access another company bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
res := domain.ConvertBet(bet)
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
// zap.Int64("betID", id),
// zap.Int("status_code", fiber.StatusOK),
// zap.Time("timestamp", time.Now()),
// )
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
}
// GetBetByFastCode godoc
// @Summary Gets bet by fast_code
// @Description Gets a single bet by fast_code
// @Tags bet
// @Accept json
// @Produce json
// @Param fast_code path int true "Bet ID"
// @Success 200 {object} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet/fastcode/{fast_code} [get]
func (h *Handler) GetBetByFastCode(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
fastCode := c.Params("fast_code")
bet, err := h.betSvc.GetBetByFastCode(c.Context(), fastCode)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get bet by fast code",
zap.String("fast_code", fastCode),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to find bet by fast code")
}
if bet.CompanyID != companyID.Value {
h.mongoLoggerSvc.Warn("User Attempt to access another company bet",
zap.String("fast_code", fastCode),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
res := domain.ConvertBet(bet)
// h.mongoLoggerSvc.Info("Bet retrieved successfully",
// zap.Int64("betID", id),
// zap.Int("status_code", fiber.StatusOK),
// zap.Time("timestamp", time.Now()),
// )
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
}
type UpdateCashOutReq struct {
CashedOut bool
}
// UpdateCashOut godoc
// @Summary Updates the cashed out field
// @Description Updates the cashed out field
// @Tags bet
// @Accept json
// @Produce json
// @Param id path int true "Bet ID"
// @Param updateCashOut body UpdateCashOutReq true "Updates Cashed Out"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [patch]
func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
type UpdateCashOutReq struct {
CashedOut bool `json:"cashed_out" validate:"required" example:"true"`
}
betID := c.Params("id")
id, err := strconv.ParseInt(betID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Error("Invalid bet ID",
zap.String("betID", betID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
}
var req UpdateCashOutReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Error("Failed to parse UpdateCashOut request",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "failed to parse request body:"+err.Error())
}
if valErrs, ok := h.validator.Validate(c, req); !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
bet, err := h.betSvc.GetBetByID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
if bet.CompanyID != companyID.Value {
h.mongoLoggerSvc.Warn("User Attempt to access another company bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
err = h.betSvc.UpdateCashOut(c.Context(), id, req.CashedOut)
if err != nil {
h.mongoLoggerSvc.Error("Failed to update cash out bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update cash out bet")
}
h.mongoLoggerSvc.Info("Bet updated successfully",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusOK),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Bet updated successfully", nil, nil)
}
// DeleteBet godoc
// @Summary Deletes bet by id
// @Description Deletes bet by id
// @Tags bet
// @Accept json
// @Produce json
// @Param id path int true "Bet ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/{tenant_slug}/sport/bet/{id} [delete]
func (h *Handler) DeleteBet(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.BadRequestLogger().Error("invalid company id")
return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
}
betID := c.Params("id")
id, err := strconv.ParseInt(betID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Error("Invalid bet ID",
zap.String("betID", betID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
}
// This is to make sure that you can remove a bet only from the right route
bet, err := h.betSvc.GetBetByID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
if bet.CompanyID != companyID.Value {
h.mongoLoggerSvc.Warn("User Attempt to access another company bet",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusNotFound),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
}
err = h.betSvc.SetBetToRemoved(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Error("Failed to delete bet by ID",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete bet:"+err.Error())
}
h.mongoLoggerSvc.Info("Bet removed successfully",
zap.Int64("betID", id),
zap.Int("status_code", fiber.StatusOK),
zap.Time("timestamp", time.Now()),
)
return response.WriteJSON(c, fiber.StatusOK, "Bet removed successfully", nil, nil)
}