Files
breakpilot-lehrer/school-service/internal/handlers/grade_handlers.go
Benjamin Boenisch 5a31f52310 Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website,
Klausur-Service, School-Service, Voice-Service, Geo-Service,
BreakPilot Drive, Agent-Core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:47:26 +01:00

217 lines
6.6 KiB
Go

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)
}