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>
217 lines
6.6 KiB
Go
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)
|
|
}
|