220 lines
7.2 KiB
Go
220 lines
7.2 KiB
Go
package handlers
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/gofiber/fiber/v2"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// CreateIssue godoc
|
|
// @Summary Report an issue
|
|
// @Description Allows a customer to report a new issue related to the betting platform
|
|
// @Tags Issues
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param issue body domain.ReportedIssue true "Issue to report"
|
|
// @Success 201 {object} domain.ReportedIssue
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/issues [post]
|
|
func (h *Handler) CreateIssue(c *fiber.Ctx) error {
|
|
role := c.Locals("role").(domain.Role)
|
|
userID := c.Locals("user_id").(int64)
|
|
|
|
var req domain.ReportedIssueReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.mongoLoggerSvc.Info("Invalid request body",
|
|
zap.Int64("userID", userID),
|
|
zap.Int("status_code", fiber.StatusBadRequest),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body:"+err.Error())
|
|
}
|
|
|
|
created, err := h.issueReportingSvc.CreateReportedIssue(c.Context(), req, userID, role)
|
|
if err != nil {
|
|
h.mongoLoggerSvc.Error("Failed to report issue",
|
|
zap.String("role", string(role)),
|
|
zap.Int64("userID", userID),
|
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "failed to report issue:"+err.Error())
|
|
}
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(created)
|
|
}
|
|
|
|
// GetUserIssues godoc
|
|
// @Summary Get reported issues by a user
|
|
// @Description Returns all issues reported by a specific user
|
|
// @Tags Issues
|
|
// @Produce json
|
|
// @Param user_id path int true "User ID"
|
|
// @Param limit query int false "Limit"
|
|
// @Param offset query int false "Offset"
|
|
// @Success 200 {array} domain.ReportedIssue
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/issues/user/{user_id} [get]
|
|
func (h *Handler) GetUserIssues(c *fiber.Ctx) error {
|
|
userID, err := strconv.ParseInt(c.Params("user_id"), 10, 64)
|
|
if err != nil {
|
|
h.mongoLoggerSvc.Info("Failed to parse user id",
|
|
zap.Int64("userID", userID),
|
|
zap.Int("status_code", fiber.StatusBadRequest),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
|
|
}
|
|
|
|
limit, offset := getPaginationParams(c)
|
|
|
|
issues, err := h.issueReportingSvc.GetIssuesForUser(c.Context(), userID, limit, offset)
|
|
if err != nil {
|
|
h.mongoLoggerSvc.Error("Failed to get user issue",
|
|
zap.Int64("userID", userID),
|
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get user issue"+err.Error())
|
|
}
|
|
|
|
return c.JSON(issues)
|
|
}
|
|
|
|
// GetAllIssues godoc
|
|
// @Summary Get all reported issues
|
|
// @Description Admin endpoint to list all reported issues with pagination
|
|
// @Tags Issues
|
|
// @Produce json
|
|
// @Param limit query int false "Limit"
|
|
// @Param offset query int false "Offset"
|
|
// @Success 200 {array} domain.ReportedIssue
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/issues [get]
|
|
func (h *Handler) GetAllIssues(c *fiber.Ctx) error {
|
|
limit, offset := getPaginationParams(c)
|
|
|
|
issues, err := h.issueReportingSvc.GetAllIssues(c.Context(), limit, offset)
|
|
if err != nil {
|
|
h.mongoLoggerSvc.Error("Failed to get all issues",
|
|
zap.Int("limit", limit),
|
|
zap.Int("offset", offset),
|
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get all issues:"+err.Error())
|
|
}
|
|
|
|
results := make([]domain.ReportedIssue, len(issues))
|
|
for i, issue := range issues {
|
|
results[i] = domain.ReportedIssue{
|
|
ID: issue.ID,
|
|
UserID: issue.UserID,
|
|
UserRole: domain.Role(issue.UserRole),
|
|
Subject: issue.Subject,
|
|
Description: issue.Description,
|
|
IssueType: domain.ReportedIssueType(issue.IssueType),
|
|
Status: domain.ReportedIssueStatus(issue.Status),
|
|
// Metadata: issue.Metadata,
|
|
CreatedAt: issue.CreatedAt.Time,
|
|
UpdatedAt: issue.UpdatedAt.Time,
|
|
}
|
|
}
|
|
|
|
return c.JSON(results)
|
|
}
|
|
|
|
// UpdateIssueStatus godoc
|
|
// @Summary Update issue status
|
|
// @Description Admin endpoint to update the status of a reported issue
|
|
// @Tags Issues
|
|
// @Accept json
|
|
// @Param issue_id path int true "Issue ID"
|
|
// @Param status body object{status=string} true "New issue status (pending, in_progress, resolved, rejected)"
|
|
// @Success 204
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Router /api/v1/issues/{issue_id}/status [patch]
|
|
func (h *Handler) UpdateIssueStatus(c *fiber.Ctx) error {
|
|
issueID, err := strconv.ParseInt(c.Params("issue_id"), 10, 64)
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid issue ID")
|
|
}
|
|
|
|
var body struct {
|
|
Status string `json:"status"`
|
|
}
|
|
if err := c.BodyParser(&body); err != nil || body.Status == "" {
|
|
h.mongoLoggerSvc.Info("Invalid status payload",
|
|
zap.Int("status_code", fiber.StatusBadRequest),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid status payload"+err.Error())
|
|
}
|
|
|
|
if err := h.issueReportingSvc.UpdateIssueStatus(c.Context(), issueID, body.Status); err != nil {
|
|
h.mongoLoggerSvc.Error("Failed to update issue status",
|
|
zap.Int64("issueID", issueID),
|
|
zap.String("status", body.Status),
|
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
|
|
}
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
|
|
// DeleteIssue godoc
|
|
// @Summary Delete a reported issue
|
|
// @Description Admin endpoint to delete a reported issue
|
|
// @Tags Issues
|
|
// @Param issue_id path int true "Issue ID"
|
|
// @Success 204
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/issues/{issue_id} [delete]
|
|
func (h *Handler) DeleteIssue(c *fiber.Ctx) error {
|
|
issueID, err := strconv.ParseInt(c.Params("issue_id"), 10, 64)
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid issue ID")
|
|
}
|
|
|
|
if err := h.issueReportingSvc.DeleteIssue(c.Context(), issueID); err != nil {
|
|
h.mongoLoggerSvc.Error("Failed to delete issue",
|
|
zap.Int64("issueID", issueID),
|
|
zap.Int("status_code", fiber.StatusInternalServerError),
|
|
zap.Error(err),
|
|
zap.Time("timestamp", time.Now()),
|
|
)
|
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
}
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
|
|
func getPaginationParams(c *fiber.Ctx) (limit, offset int) {
|
|
limit = 20
|
|
offset = 0
|
|
|
|
if l, err := strconv.Atoi(c.Query("limit")); err == nil && l > 0 {
|
|
limit = l
|
|
}
|
|
if o, err := strconv.Atoi(c.Query("offset")); err == nil && o >= 0 {
|
|
offset = o
|
|
}
|
|
return
|
|
}
|