Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,11 @@ const docTemplate = `{
},
"/api/exams": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve a list of all exams",
"produces": [
"application/json"
Expand Down Expand Up @@ -749,7 +754,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.Exam"
"$ref": "#/definitions/handlers.UpdateExamRequest"
}
}
],
Expand All @@ -765,7 +770,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Exam"
"$ref": "#/definitions/handlers.UpdateExamRequest"
}
}
}
Expand Down Expand Up @@ -955,6 +960,11 @@ const docTemplate = `{
},
"/api/exams/{id}/exam": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve basic information about an exam, including title, description, start and end times",
"produces": [
"application/json"
Expand Down Expand Up @@ -4671,6 +4681,28 @@ const docTemplate = `{
}
}
},
"handlers.UpdateExamRequest": {
"type": "object",
"required": [
"title"
],
"properties": {
"description": {
"type": "string"
},
"end_time": {
"type": "string",
"example": "2006-01-02T15:04:05Z"
},
"start_time": {
"type": "string",
"example": "2006-01-02T15:04:05Z"
},
"title": {
"type": "string"
}
}
},
"handlers.UpdateUserInfoDTO": {
"type": "object",
"properties": {
Expand Down
36 changes: 34 additions & 2 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,11 @@
},
"/api/exams": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve a list of all exams",
"produces": [
"application/json"
Expand Down Expand Up @@ -742,7 +747,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.Exam"
"$ref": "#/definitions/handlers.UpdateExamRequest"
}
}
],
Expand All @@ -758,7 +763,7 @@
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Exam"
"$ref": "#/definitions/handlers.UpdateExamRequest"
}
}
}
Expand Down Expand Up @@ -948,6 +953,11 @@
},
"/api/exams/{id}/exam": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve basic information about an exam, including title, description, start and end times",
"produces": [
"application/json"
Expand Down Expand Up @@ -4664,6 +4674,28 @@
}
}
},
"handlers.UpdateExamRequest": {
"type": "object",
"required": [
"title"
],
"properties": {
"description": {
"type": "string"
},
"end_time": {
"type": "string",
"example": "2006-01-02T15:04:05Z"
},
"start_time": {
"type": "string",
"example": "2006-01-02T15:04:05Z"
},
"title": {
"type": "string"
}
}
},
"handlers.UpdateUserInfoDTO": {
"type": "object",
"properties": {
Expand Down
23 changes: 21 additions & 2 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,21 @@ definitions:
- question_title
- score
type: object
handlers.UpdateExamRequest:
properties:
description:
type: string
end_time:
example: "2006-01-02T15:04:05Z"
type: string
start_time:
example: "2006-01-02T15:04:05Z"
type: string
title:
type: string
required:
- title
type: object
handlers.UpdateUserInfoDTO:
properties:
enable:
Expand Down Expand Up @@ -1597,6 +1612,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ResponseHTTP'
security:
- BearerAuth: []
summary: List all exams
tags:
- Exam
Expand Down Expand Up @@ -1630,6 +1647,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ResponseHTTP'
security:
- BearerAuth: []
summary: Get basic information about an exam
tags:
- Exam
Expand Down Expand Up @@ -1876,7 +1895,7 @@ paths:
name: exam
required: true
schema:
$ref: '#/definitions/models.Exam'
$ref: '#/definitions/handlers.UpdateExamRequest'
produces:
- application/json
responses:
Expand All @@ -1887,7 +1906,7 @@ paths:
- $ref: '#/definitions/handlers.ResponseHTTP'
- properties:
data:
$ref: '#/definitions/models.Exam'
$ref: '#/definitions/handlers.UpdateExamRequest'
type: object
"400":
description: Bad Request
Expand Down
54 changes: 49 additions & 5 deletions handlers/exam.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,22 @@ func GetExam(c *gin.Context) {
})
}

type UpdateExamRequest struct {
Title string `json:"title" binding:"required"`
Description string `json:"description"`
StartTime time.Time `json:"start_time" example:"2006-01-02T15:04:05Z" time_format:"RFC3339"`
EndTime time.Time `json:"end_time" example:"2006-01-02T15:04:05Z" time_format:"RFC3339"`
}

// UpdateExam updates an existing exam
// @Summary Update an existing exam
// @Description Update the details of an existing exam by ID
// @Tags Exam
// @Accept json
// @Produce json
// @Param id path string true "Exam ID"
// @Param exam body models.Exam true "Updated exam details"
// @Success 200 {object} ResponseHTTP{data=models.Exam}
// @Param exam body UpdateExamRequest true "Updated exam details"
// @Success 200 {object} ResponseHTTP{data=UpdateExamRequest}
// @Failure 400 {object} ResponseHTTP{}
// @Failure 404 {object} ResponseHTTP{}
// @Failure 500 {object} ResponseHTTP{}
Expand All @@ -147,10 +154,11 @@ func UpdateExam(c *gin.Context) {
}

id := c.Param("id")
var exam models.Exam
var exam UpdateExamRequest
var existingExam models.Exam

db := database.DBConn
if err := db.First(&exam, id).Error; err != nil {
if err := db.First(&existingExam, id).Error; err != nil {
c.JSON(http.StatusNotFound, ResponseHTTP{
Success: false,
Message: "Exam not found",
Expand All @@ -165,15 +173,51 @@ func UpdateExam(c *gin.Context) {
})
return
}
// Validate that start time is before end time if both are provided
if !exam.StartTime.IsZero() && !exam.EndTime.IsZero() && exam.StartTime.After(exam.EndTime) {
c.JSON(http.StatusBadRequest, ResponseHTTP{
Success: false,
Message: "Start time must be before end time",
})
return
}
if exam.Title != "" {
existingExam.Title = exam.Title
}
if exam.Description != "" {
existingExam.Description = exam.Description
}
if !exam.StartTime.IsZero() {
existingExam.StartTime = exam.StartTime
}
if !exam.EndTime.IsZero() {
existingExam.EndTime = exam.EndTime
}

if err := db.Save(&exam).Error; err != nil {
if err := db.Save(&existingExam).Error; err != nil {
c.JSON(http.StatusInternalServerError, ResponseHTTP{
Success: false,
Message: "Failed to update exam",
})
return
}

// update exam questions's start and end time if exam time is updated
if !exam.StartTime.IsZero() || !exam.EndTime.IsZero() {
if err := db.Model(&models.Question{}).
Where("id IN (SELECT question_id FROM exam_questions WHERE exam_id = ?)", id).
Updates(map[string]any{
"start_time": exam.StartTime,
"end_time": exam.EndTime,
}).Error; err != nil {
c.JSON(http.StatusInternalServerError, ResponseHTTP{
Success: false,
Message: "Failed to update exam questions",
})
return
}
}

c.JSON(http.StatusOK, ResponseHTTP{
Success: true,
Data: exam,
Expand Down