305 lines
9.4 KiB
Go
305 lines
9.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"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"
|
|
)
|
|
|
|
// 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 /bet [post]
|
|
func (h *Handler) CreateBet(c *fiber.Ctx) error {
|
|
|
|
// Get user_id from middleware
|
|
userID := c.Locals("user_id").(int64)
|
|
role := c.Locals("role").(domain.Role)
|
|
|
|
var req domain.CreateBetReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse CreateBet request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
valErrs, ok := h.validator.Validate(c, req)
|
|
if !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
res, err := h.betSvc.PlaceBet(c.Context(), req, userID, role)
|
|
|
|
if err != nil {
|
|
h.logger.Error("PlaceBet failed", "error", err)
|
|
switch err {
|
|
case bet.ErrEventHasBeenRemoved, bet.ErrEventHasNotEnded, bet.ErrRawOddInvalid, wallet.ErrBalanceInsufficient:
|
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
}
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create bet")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Bet Created", 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 /random/bet [post]
|
|
func (h *Handler) RandomBet(c *fiber.Ctx) error {
|
|
|
|
// Get user_id from middleware
|
|
userID := c.Locals("user_id").(int64)
|
|
// role := c.Locals("role").(domain.Role)
|
|
|
|
leagueIDQuery := c.Query("league_id")
|
|
sportIDQuery := c.Query("sport_id")
|
|
firstStartTimeQuery := c.Query("first_start_time")
|
|
lastStartTimeQuery := c.Query("last_start_time")
|
|
|
|
leagueID := domain.ValidString{
|
|
Value: leagueIDQuery,
|
|
Valid: leagueIDQuery != "",
|
|
}
|
|
sportID := domain.ValidString{
|
|
Value: sportIDQuery,
|
|
Valid: sportIDQuery != "",
|
|
}
|
|
|
|
var firstStartTime domain.ValidTime
|
|
if firstStartTimeQuery != "" {
|
|
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
|
|
if err != nil {
|
|
h.logger.Error("invalid start_time format", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
|
}
|
|
firstStartTime = domain.ValidTime{
|
|
Value: firstStartTimeParsed,
|
|
Valid: true,
|
|
}
|
|
}
|
|
var lastStartTime domain.ValidTime
|
|
if lastStartTimeQuery != "" {
|
|
lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery)
|
|
if err != nil {
|
|
h.logger.Error("invalid start_time format", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
|
|
}
|
|
lastStartTime = domain.ValidTime{
|
|
Value: lastStartTimeParsed,
|
|
Valid: true,
|
|
}
|
|
}
|
|
|
|
var req domain.RandomBetReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse RandomBet request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
valErrs, ok := h.validator.Validate(c, req)
|
|
if !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
var res domain.CreateBetRes
|
|
var err error
|
|
for i := 0; i < int(req.NumberOfBets); i++ {
|
|
res, err = h.betSvc.PlaceRandomBet(c.Context(), userID, req.BranchID, leagueID, sportID, firstStartTime, lastStartTime)
|
|
|
|
if err != nil {
|
|
h.logger.Error("Random Bet failed", "error", err)
|
|
switch err {
|
|
case bet.ErrNoEventsAvailable:
|
|
return fiber.NewError(fiber.StatusBadRequest, "No events found")
|
|
}
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Unable to create random bet")
|
|
}
|
|
}
|
|
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 /bet [get]
|
|
func (h *Handler) GetAllBet(c *fiber.Ctx) error {
|
|
bets, err := h.betSvc.GetAllBets(c.Context())
|
|
if err != nil {
|
|
h.logger.Error("Failed to get bets", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets")
|
|
}
|
|
|
|
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 /bet/{id} [get]
|
|
func (h *Handler) GetBetByID(c *fiber.Ctx) error {
|
|
betID := c.Params("id")
|
|
id, err := strconv.ParseInt(betID, 10, 64)
|
|
if err != nil {
|
|
h.logger.Error("Invalid bet ID", "betID", betID, "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
|
}
|
|
|
|
bet, err := h.betSvc.GetBetByID(c.Context(), id)
|
|
if err != nil {
|
|
// TODO: handle all the errors types
|
|
h.logger.Error("Failed to get bet by ID", "betID", id, "error", err)
|
|
return fiber.NewError(fiber.StatusNotFound, "Failed to retrieve bet")
|
|
}
|
|
|
|
res := domain.ConvertBet(bet)
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Bet retrieved successfully", res, nil)
|
|
|
|
}
|
|
|
|
// GetBetByCashoutID godoc
|
|
// @Summary Gets bet by cashout id
|
|
// @Description Gets a single bet by cashout id
|
|
// @Tags bet
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path string true "cashout ID"
|
|
// @Success 200 {object} domain.BetRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /bet/cashout/{id} [get]
|
|
func (h *Handler) GetBetByCashoutID(c *fiber.Ctx) error {
|
|
cashoutID := c.Params("id")
|
|
// id, err := strconv.ParseInt(cashoutID, 10, 64)
|
|
|
|
// if err != nil {
|
|
// logger.Error("Invalid cashout ID", "cashoutID", cashoutID, "error", err)
|
|
// return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashout ID", err, 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 := domain.ConvertBet(bet)
|
|
|
|
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 /bet/{id} [patch]
|
|
func (h *Handler) UpdateCashOut(c *fiber.Ctx) error {
|
|
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.logger.Error("Invalid bet ID", "betID", betID, "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
|
}
|
|
|
|
var req UpdateCashOutReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse UpdateCashOut request", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request body", err, nil)
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
err = h.betSvc.UpdateCashOut(c.Context(), id, req.CashedOut)
|
|
if err != nil {
|
|
h.logger.Error("Failed to update cash out bet", "betID", id, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update cash out bet")
|
|
}
|
|
|
|
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 /bet/{id} [delete]
|
|
func (h *Handler) DeleteBet(c *fiber.Ctx) error {
|
|
betID := c.Params("id")
|
|
id, err := strconv.ParseInt(betID, 10, 64)
|
|
if err != nil {
|
|
h.logger.Error("Invalid bet ID", "betID", betID, "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet ID")
|
|
}
|
|
|
|
err = h.betSvc.DeleteBet(c.Context(), id)
|
|
if err != nil {
|
|
h.logger.Error("Failed to delete bet by ID", "betID", id, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete bet")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Bet removed successfully", nil, nil)
|
|
}
|