760 lines
24 KiB
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, _ := 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)
|
|
}
|