quzuu-api-test / controllers /admin_event_controller.go
lifedebugger's picture
Deploy files from GitHub repository
875ef91
package controllers
import (
"strconv"
"abdanhafidz.com/go-boilerplate/models/dto"
entity "abdanhafidz.com/go-boilerplate/models/entity"
http_error "abdanhafidz.com/go-boilerplate/models/error"
"abdanhafidz.com/go-boilerplate/services"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type AdminEventController interface {
ListEvents(ctx *gin.Context)
CreateEvent(ctx *gin.Context)
UpdateEvent(ctx *gin.Context)
DeleteEvent(ctx *gin.Context)
ListParticipants(ctx *gin.Context)
ListCandidates(ctx *gin.Context)
ListExamCandidates(ctx *gin.Context)
AddParticipant(ctx *gin.Context)
RemoveParticipant(ctx *gin.Context)
ListEventExams(ctx *gin.Context)
RemoveExam(ctx *gin.Context)
ListResults(ctx *gin.Context)
GetAttemptReview(ctx *gin.Context)
UpdateResult(ctx *gin.Context)
DeleteResult(ctx *gin.Context)
}
type adminEventController struct {
adminEventService services.AdminEventService
}
func NewAdminEventController(adminEventService services.AdminEventService) AdminEventController {
return &adminEventController{adminEventService: adminEventService}
}
// ListEvents godoc
// @Summary Admin: List Events
// @Description Admin view of all events with participant count, exam count and optional filters/pagination
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by title / slug / event code"
// @Param sortBy query string false "Sort field (title, start_event, end_event, created_at, participant_count, exam_count)"
// @Param order query string false "Sort direction (asc / desc)"
// @Param status query string false "Filter by status (UPCOMING, ONGOING, ENDED)"
// @Success 200 {object} dto.SuccessResponse[[]dto.AdminEventResponse]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events [get]
func (c *adminEventController) ListEvents(ctx *gin.Context) {
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
order := ctx.DefaultQuery("order", "")
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
var status *string
if val := ctx.Query("status"); val != "" {
if val == entity.EventStatusUpcoming || val == entity.EventStatusOngoing || val == entity.EventStatusEnded {
status = &val
}
}
offset := (page - 1) * limit
p := entity.Pagination{
Limit: limit,
Offset: offset,
Search: search,
SortBy: sortBy,
Order: order,
Status: status,
}
list, total, err := c.adminEventService.ListEvents(ctx.Request.Context(), p)
if err != nil {
ResponseJSON[any, any](ctx, nil, nil, err)
return
}
var totalPages int
if total == 0 {
totalPages = 1
} else {
totalPages = int((total + int64(limit) - 1) / int64(limit))
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// GetAttemptReview godoc
// @Summary Admin: Review Exam Attempt
// @Description Review a specific participant attempt for an event exam
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param attempt_id path string true "Attempt ID"
// @Param user_id path string true "User ID"
// @Success 200 {object} dto.SuccessResponse[dto.AdminExamReviewResponse]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/attempts/{attempt_id}/{user_id}/review [get]
func (c *adminEventController) GetAttemptReview(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
attemptId, err := uuid.Parse(ctx.Param("attempt_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"attempt_id": ctx.Param("attempt_id")}, nil, http_error.INVALID_TOKEN)
return
}
userId, err := uuid.Parse(ctx.Param("user_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"user_id": ctx.Param("user_id")}, nil, http_error.INVALID_TOKEN)
return
}
review, reviewErr := c.adminEventService.GetAttemptReview(ctx.Request.Context(), eventId, attemptId, userId)
ResponseJSON(ctx, gin.H{"event_id": eventId, "attempt_id": attemptId, "user_id": userId}, review, reviewErr)
}
// CreateEvent godoc
// @Summary Admin: Create Event
// @Description Create a new event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CreateEventRequest true "Create Event Request"
// @Success 200 {object} dto.SuccessResponse[entity.Events]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events [post]
func (c *adminEventController) CreateEvent(ctx *gin.Context) {
req := RequestJSON[dto.CreateEventRequest](ctx)
res, err := c.adminEventService.CreateEvent(ctx.Request.Context(), req)
ResponseJSON(ctx, req, res, err)
}
// UpdateEvent godoc
// @Summary Admin: Update Event
// @Description Update an existing event by ID
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param request body dto.UpdateEventRequest true "Update Event Request"
// @Success 200 {object} dto.SuccessResponse[entity.Events]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id} [put]
func (c *adminEventController) UpdateEvent(ctx *gin.Context) {
id, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
req := RequestJSON[dto.UpdateEventRequest](ctx)
res, err := c.adminEventService.UpdateEvent(ctx.Request.Context(), id, req)
ResponseJSON(ctx, req, res, err)
}
// DeleteEvent godoc
// @Summary Admin: Delete Event
// @Description Delete an event by ID
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Success 200 {object} dto.SuccessResponse[map[string]bool]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id} [delete]
func (c *adminEventController) DeleteEvent(ctx *gin.Context) {
id, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
delErr := c.adminEventService.DeleteEvent(ctx.Request.Context(), id)
ResponseJSON(ctx, gin.H{"id": id}, gin.H{"deleted": delErr == nil}, delErr)
}
// ListParticipants godoc
// @Summary Admin: List Event Participants
// @Description List all participants assigned to an event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by username / full name"
// @Param sortBy query string false "Sort field (assigned_at, username, email, full_name)"
// @Param order query string false "Sort direction (asc / desc)"
// @Success 200 {object} dto.SuccessResponse[[]entity.EventAssign]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/participants [get]
func (c *adminEventController) ListParticipants(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
order := ctx.DefaultQuery("order", "")
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
offset := (page - 1) * limit
p := entity.Pagination{Limit: limit, Offset: offset, Search: search, SortBy: sortBy, Order: order}
list, total, listErr := c.adminEventService.ListParticipants(ctx.Request.Context(), eventId, p)
if listErr != nil {
ResponseJSON[any, any](ctx, nil, nil, listErr)
return
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
if total == 0 {
totalPages = 1
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"event_id": eventId,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// ListCandidates godoc
// @Summary Admin: List of Event Candidates
// @Description List accounts that are not yet assigned to the event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by username / full name"
// @Param sortBy query string false "Sort field (username, full_name, created_at)"
// @Param orderBy query string false "Sort direction (asc / desc)"
// @Success 200 {object} dto.SuccessResponse[[]entity.Account]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/candidate [get]
func (c *adminEventController) ListCandidates(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
order := ctx.DefaultQuery("orderBy", "")
if order == "" {
order = ctx.DefaultQuery("order", "")
}
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
offset := (page - 1) * limit
p := entity.Pagination{
Limit: limit,
Offset: offset,
Search: search,
SortBy: sortBy,
Order: order,
}
list, total, listErr := c.adminEventService.ListCandidates(ctx.Request.Context(), eventId, p)
if listErr != nil {
ResponseJSON[any, any](ctx, nil, nil, listErr)
return
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
if total == 0 {
totalPages = 1
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"event_id": eventId,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// ListExamCandidates godoc
// @Summary Admin: List Exam Candidates for Event
// @Description List exams that are not yet assigned to the event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by exam title / slug"
// @Param sortBy query string false "Sort field (title, slug, created_at, duration)"
// @Param orderBy query string false "Sort direction (asc / desc)"
// @Success 200 {object} dto.SuccessResponse[[]entity.Exam]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams/candidate [get]
func (c *adminEventController) ListExamCandidates(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
if sortBy == "" {
sortBy = ctx.DefaultQuery("sortby", "")
}
order := ctx.DefaultQuery("orderBy", "")
if order == "" {
order = ctx.DefaultQuery("orderby", "")
}
if order == "" {
order = ctx.DefaultQuery("order", "")
}
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
offset := (page - 1) * limit
p := entity.Pagination{
Limit: limit,
Offset: offset,
Search: search,
SortBy: sortBy,
Order: order,
}
list, total, listErr := c.adminEventService.ListExamCandidates(ctx.Request.Context(), eventId, p)
if listErr != nil {
ResponseJSON[any, any](ctx, nil, nil, listErr)
return
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
if total == 0 {
totalPages = 1
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"event_id": eventId,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// AddParticipant godoc
// @Summary Admin: Add Participant to Event
// @Description Manually assign a user to an event (bypasses payment)
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param request body dto.AddParticipantRequest true "Add Participant Request"
// @Success 200 {object} dto.SuccessResponse[entity.EventAssign]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/participants [post]
func (c *adminEventController) AddParticipant(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
req := RequestJSON[dto.AddParticipantRequest](ctx)
userId, parseErr := uuid.Parse(req.UserId)
if parseErr != nil {
ResponseJSON[any](ctx, req, nil, http_error.INVALID_TOKEN)
return
}
assign, err := c.adminEventService.AddParticipant(ctx.Request.Context(), eventId, userId)
ResponseJSON(ctx, req, assign, err)
}
// RemoveParticipant godoc
// @Summary Admin: Remove Participant from Event
// @Description Unassign a user from an event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param user_id path string true "User ID"
// @Success 200 {object} dto.SuccessResponse[map[string]bool]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/participants/{user_id} [delete]
func (c *adminEventController) RemoveParticipant(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
userId, err := uuid.Parse(ctx.Param("user_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"user_id": ctx.Param("user_id")}, nil, http_error.INVALID_TOKEN)
return
}
delErr := c.adminEventService.RemoveParticipant(ctx.Request.Context(), eventId, userId)
ResponseJSON(ctx, gin.H{"event_id": eventId, "user_id": userId}, gin.H{"removed": delErr == nil}, delErr)
}
// ListEventExams godoc
// @Summary Admin: List Event Exams
// @Description List all exams assigned to an event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by exam title / slug"
// @Param sortBy query string false "Sort field (title, slug, created_at, duration)"
// @Param order query string false "Sort direction (asc / desc)"
// @Success 200 {object} dto.SuccessResponse[[]entity.EventExamAssign]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams [get]
func (c *adminEventController) ListEventExams(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
order := ctx.DefaultQuery("order", "")
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
offset := (page - 1) * limit
p := entity.Pagination{Limit: limit, Offset: offset, Search: search, SortBy: sortBy, Order: order}
list, total, listErr := c.adminEventService.ListEventExams(ctx.Request.Context(), eventId, p)
if listErr != nil {
ResponseJSON[any, any](ctx, nil, nil, listErr)
return
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
if total == 0 {
totalPages = 1
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"event_id": eventId,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// RemoveExam godoc
// @Summary Admin: Remove Exam from Event
// @Description Unassign an exam from an event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param exam_id path string true "Exam ID"
// @Success 200 {object} dto.SuccessResponse[map[string]bool]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams/{exam_id} [delete]
func (c *adminEventController) RemoveExam(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
examId, err := uuid.Parse(ctx.Param("exam_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"exam_id": ctx.Param("exam_id")}, nil, http_error.INVALID_TOKEN)
return
}
delErr := c.adminEventService.RemoveExam(ctx.Request.Context(), eventId, examId)
ResponseJSON(ctx, gin.H{"event_id": eventId, "exam_id": examId}, gin.H{"removed": delErr == nil}, delErr)
}
// ListResults godoc
// @Summary Admin: List Exam Results for an Event
// @Description Retrieve all participant results for a specific exam within an event
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param exam_id path string true "Exam ID"
// @Param limit query int false "Items per page" default(10)
// @Param page query int false "Page number" default(1)
// @Param search query string false "Search by username / full name"
// @Param sortBy query string false "Sort field (final_score, created_at, username, full_name)"
// @Param order query string false "Sort direction (asc / desc)"
// @Success 200 {object} dto.SuccessResponse[[]entity.Result]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams/{exam_id}/results [get]
func (c *adminEventController) ListResults(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
examId, err := uuid.Parse(ctx.Param("exam_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"exam_id": ctx.Param("exam_id")}, nil, http_error.INVALID_TOKEN)
return
}
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
search := ctx.DefaultQuery("search", "")
sortBy := ctx.DefaultQuery("sortBy", "")
if sortBy == "" {
sortBy = ctx.DefaultQuery("sortby", "")
}
order := ctx.DefaultQuery("order", "")
if order == "" {
order = ctx.DefaultQuery("orderBy", "")
}
if order == "" {
order = ctx.DefaultQuery("orderby", "")
}
if limit < 1 {
limit = 10
} else if limit > 100 {
limit = 100
}
if page < 1 {
page = 1
}
offset := (page - 1) * limit
p := entity.Pagination{Limit: limit, Offset: offset, Search: search, SortBy: sortBy, Order: order}
list, total, listErr := c.adminEventService.ListResults(ctx.Request.Context(), eventId, examId, p)
if listErr != nil {
ResponseJSON[any, any](ctx, nil, nil, listErr)
return
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
if total == 0 {
totalPages = 1
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"event_id": eventId,
"exam_id": examId,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, list, nil)
}
// UpdateResult godoc
// @Summary Admin: Update Exam Result
// @Description Edit the final score of a participant's exam result
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param exam_id path string true "Exam ID"
// @Param result_id path string true "Result ID"
// @Param request body dto.UpdateResultRequest true "Update Result Request"
// @Success 200 {object} dto.SuccessResponse[entity.Result]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams/{exam_id}/results/{result_id} [put]
func (c *adminEventController) UpdateResult(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
examId, err := uuid.Parse(ctx.Param("exam_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"exam_id": ctx.Param("exam_id")}, nil, http_error.INVALID_TOKEN)
return
}
resultId, err := uuid.Parse(ctx.Param("result_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"result_id": ctx.Param("result_id")}, nil, http_error.INVALID_TOKEN)
return
}
req := RequestJSON[dto.UpdateResultRequest](ctx)
res, err := c.adminEventService.UpdateResult(ctx.Request.Context(), eventId, examId, resultId, req)
ResponseJSON(ctx, req, res, err)
}
// DeleteResult godoc
// @Summary Admin: Delete Exam Result
// @Description Delete a participant's exam result
// @Tags AdminEvent
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param event_id path string true "Event ID"
// @Param exam_id path string true "Exam ID"
// @Param result_id path string true "Result ID"
// @Success 200 {object} dto.SuccessResponse[map[string]bool]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/admin/events/{event_id}/exams/{exam_id}/results/{result_id} [delete]
func (c *adminEventController) DeleteResult(ctx *gin.Context) {
eventId, err := uuid.Parse(ctx.Param("event_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"event_id": ctx.Param("event_id")}, nil, http_error.INVALID_TOKEN)
return
}
examId, err := uuid.Parse(ctx.Param("exam_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"exam_id": ctx.Param("exam_id")}, nil, http_error.INVALID_TOKEN)
return
}
resultId, err := uuid.Parse(ctx.Param("result_id"))
if err != nil {
ResponseJSON[any](ctx, gin.H{"result_id": ctx.Param("result_id")}, nil, http_error.INVALID_TOKEN)
return
}
delErr := c.adminEventService.DeleteResult(ctx.Request.Context(), eventId, examId, resultId)
ResponseJSON(ctx, gin.H{"result_id": resultId}, gin.H{"deleted": delErr == nil}, delErr)
}