package handlers import ( "net/http" "strconv" "github.com/breakpilot/school-service/internal/models" "github.com/gin-gonic/gin" ) // GetClassGrades returns grades for a class func (h *Handler) GetClassGrades(c *gin.Context) { classID := c.Param("classId") semesterStr := c.DefaultQuery("semester", "1") semester, err := strconv.Atoi(semesterStr) if err != nil || semester < 1 || semester > 2 { semester = 1 } grades, err := h.gradeService.GetGradeOverview(c.Request.Context(), classID, semester) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get grades: "+err.Error()) return } respondSuccess(c, grades) } // GetStudentGrades returns all grades for a student func (h *Handler) GetStudentGrades(c *gin.Context) { studentID := c.Param("studentId") grades, err := h.gradeService.GetStudentGrades(c.Request.Context(), studentID) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get grades: "+err.Error()) return } respondSuccess(c, grades) } // UpdateOralGrade updates the oral grade for a student func (h *Handler) UpdateOralGrade(c *gin.Context) { studentID := c.Param("studentId") subjectID := c.Param("subjectId") var req models.UpdateOralGradeRequest if err := c.ShouldBindJSON(&req); err != nil { respondError(c, http.StatusBadRequest, "Invalid request: "+err.Error()) return } grade, err := h.gradeService.UpdateOralGrade(c.Request.Context(), studentID, subjectID, &req) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to update oral grade: "+err.Error()) return } respondSuccess(c, grade) } // CalculateFinalGrades calculates final grades for a class func (h *Handler) CalculateFinalGrades(c *gin.Context) { var req struct { ClassID string `json:"class_id" binding:"required"` Semester int `json:"semester" binding:"required,min=1,max=2"` } if err := c.ShouldBindJSON(&req); err != nil { respondError(c, http.StatusBadRequest, "Invalid request: "+err.Error()) return } if err := h.gradeService.CalculateFinalGrades(c.Request.Context(), req.ClassID, req.Semester); err != nil { respondError(c, http.StatusInternalServerError, "Failed to calculate grades: "+err.Error()) return } c.JSON(http.StatusOK, gin.H{"message": "Grades calculated successfully"}) } // TransferApprovedGrades transfers approved exam results to grade overview func (h *Handler) TransferApprovedGrades(c *gin.Context) { teacherID := getUserID(c) if teacherID == "" { respondError(c, http.StatusUnauthorized, "User not authenticated") return } if err := h.gradeService.TransferApprovedGrades(c.Request.Context(), teacherID); err != nil { respondError(c, http.StatusInternalServerError, "Failed to transfer grades: "+err.Error()) return } c.JSON(http.StatusOK, gin.H{"message": "Grades transferred successfully"}) } // LockFinalGrade locks a final grade func (h *Handler) LockFinalGrade(c *gin.Context) { studentID := c.Param("studentId") subjectID := c.Param("subjectId") semesterStr := c.DefaultQuery("semester", "1") semester, err := strconv.Atoi(semesterStr) if err != nil || semester < 1 || semester > 2 { semester = 1 } if err := h.gradeService.LockFinalGrade(c.Request.Context(), studentID, subjectID, semester); err != nil { respondError(c, http.StatusInternalServerError, "Failed to lock grade: "+err.Error()) return } c.JSON(http.StatusOK, gin.H{"message": "Grade locked"}) } // UpdateGradeWeights updates the grade weights func (h *Handler) UpdateGradeWeights(c *gin.Context) { studentID := c.Param("studentId") subjectID := c.Param("subjectId") var req struct { WrittenWeight int `json:"written_weight" binding:"required,min=0,max=100"` OralWeight int `json:"oral_weight" binding:"required,min=0,max=100"` } if err := c.ShouldBindJSON(&req); err != nil { respondError(c, http.StatusBadRequest, "Invalid request: "+err.Error()) return } if req.WrittenWeight+req.OralWeight != 100 { respondError(c, http.StatusBadRequest, "Weights must sum to 100") return } if err := h.gradeService.UpdateGradeWeights(c.Request.Context(), studentID, subjectID, req.WrittenWeight, req.OralWeight); err != nil { respondError(c, http.StatusInternalServerError, "Failed to update weights: "+err.Error()) return } c.JSON(http.StatusOK, gin.H{"message": "Weights updated"}) } // ============================================= // STATISTICS ENDPOINTS // ============================================= // GetClassStatistics returns grade statistics for a class // GET /api/v1/school/statistics/:classId func (h *Handler) GetClassStatistics(c *gin.Context) { classID := c.Param("classId") semesterStr := c.DefaultQuery("semester", "0") // 0 = both semesters semester, _ := strconv.Atoi(semesterStr) stats, err := h.gradeService.GetClassStatistics(c.Request.Context(), classID, semester) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get statistics: "+err.Error()) return } respondSuccess(c, stats) } // GetSubjectStatistics returns grade statistics for a specific subject in a class // GET /api/v1/school/statistics/:classId/subject/:subjectId func (h *Handler) GetSubjectStatistics(c *gin.Context) { classID := c.Param("classId") subjectID := c.Param("subjectId") semesterStr := c.DefaultQuery("semester", "0") semester, _ := strconv.Atoi(semesterStr) stats, err := h.gradeService.GetSubjectStatistics(c.Request.Context(), classID, subjectID, semester) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get statistics: "+err.Error()) return } respondSuccess(c, stats) } // GetStudentStatistics returns grade statistics for a specific student // GET /api/v1/school/statistics/student/:studentId func (h *Handler) GetStudentStatistics(c *gin.Context) { studentID := c.Param("studentId") stats, err := h.gradeService.GetStudentStatistics(c.Request.Context(), studentID) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get statistics: "+err.Error()) return } respondSuccess(c, stats) } // GetNotenspiegel returns the grade distribution for a class or exam // GET /api/v1/school/statistics/:classId/notenspiegel func (h *Handler) GetNotenspiegel(c *gin.Context) { classID := c.Param("classId") subjectID := c.Query("subject_id") examID := c.Query("exam_id") semesterStr := c.DefaultQuery("semester", "0") semester, _ := strconv.Atoi(semesterStr) notenspiegel, err := h.gradeService.GetNotenspiegel(c.Request.Context(), classID, subjectID, examID, semester) if err != nil { respondError(c, http.StatusInternalServerError, "Failed to get Notenspiegel: "+err.Error()) return } respondSuccess(c, notenspiegel) }