A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
330 lines
14 KiB
Go
330 lines
14 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// SchoolYear represents a school year
|
|
type SchoolYear struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
Name string `json:"name" db:"name"`
|
|
StartDate time.Time `json:"start_date" db:"start_date"`
|
|
EndDate time.Time `json:"end_date" db:"end_date"`
|
|
IsCurrent bool `json:"is_current" db:"is_current"`
|
|
TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// Class represents a school class
|
|
type Class struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
|
|
SchoolYearID *uuid.UUID `json:"school_year_id,omitempty" db:"school_year_id"`
|
|
Name string `json:"name" db:"name"`
|
|
GradeLevel int `json:"grade_level" db:"grade_level"`
|
|
SchoolType string `json:"school_type,omitempty" db:"school_type"`
|
|
FederalState string `json:"federal_state,omitempty" db:"federal_state"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
StudentCount int `json:"student_count,omitempty"` // Computed field
|
|
}
|
|
|
|
// Student represents a student
|
|
type Student struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
ClassID uuid.UUID `json:"class_id" db:"class_id"`
|
|
FirstName string `json:"first_name" db:"first_name"`
|
|
LastName string `json:"last_name" db:"last_name"`
|
|
BirthDate *time.Time `json:"birth_date,omitempty" db:"date_of_birth"`
|
|
StudentNumber *string `json:"student_number,omitempty" db:"student_number"`
|
|
Notes *string `json:"notes,omitempty" db:"notes"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// Subject represents a school subject
|
|
type Subject struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
|
|
Name string `json:"name" db:"name"`
|
|
ShortName string `json:"short_name,omitempty" db:"short_name"`
|
|
IsMainSubject bool `json:"is_main_subject" db:"is_main_subject"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// ExamType represents types of exams
|
|
type ExamType string
|
|
|
|
const (
|
|
ExamTypeKlassenarbeit ExamType = "klassenarbeit"
|
|
ExamTypeTest ExamType = "test"
|
|
ExamTypeKlausur ExamType = "klausur"
|
|
)
|
|
|
|
// ExamStatus represents exam status
|
|
type ExamStatus string
|
|
|
|
const (
|
|
ExamStatusDraft ExamStatus = "draft"
|
|
ExamStatusActive ExamStatus = "active"
|
|
ExamStatusArchived ExamStatus = "archived"
|
|
)
|
|
|
|
// Exam represents an exam/test
|
|
type Exam struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
|
|
ClassID *uuid.UUID `json:"class_id,omitempty" db:"class_id"`
|
|
SubjectID *uuid.UUID `json:"subject_id,omitempty" db:"subject_id"`
|
|
Title string `json:"title" db:"title"`
|
|
ExamType ExamType `json:"exam_type" db:"exam_type"`
|
|
Topic string `json:"topic,omitempty" db:"topic"`
|
|
Content string `json:"content,omitempty" db:"content"`
|
|
SourceFilePath string `json:"source_file_path,omitempty" db:"source_file_path"`
|
|
DifficultyLevel int `json:"difficulty_level" db:"difficulty_level"`
|
|
DurationMinutes *int `json:"duration_minutes,omitempty" db:"duration_minutes"`
|
|
MaxPoints *float64 `json:"max_points,omitempty" db:"max_points"`
|
|
IsTemplate bool `json:"is_template" db:"is_template"`
|
|
ParentExamID *uuid.UUID `json:"parent_exam_id,omitempty" db:"parent_exam_id"`
|
|
Status ExamStatus `json:"status" db:"status"`
|
|
ExamDate *time.Time `json:"exam_date,omitempty" db:"exam_date"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
|
|
// Computed/joined fields
|
|
ClassName string `json:"class_name,omitempty"`
|
|
SubjectName string `json:"subject_name,omitempty"`
|
|
}
|
|
|
|
// ExamResult represents a student's exam result
|
|
type ExamResult struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
ExamID uuid.UUID `json:"exam_id" db:"exam_id"`
|
|
StudentID uuid.UUID `json:"student_id" db:"student_id"`
|
|
PointsAchieved *float64 `json:"points_achieved,omitempty" db:"points_achieved"`
|
|
Grade *float64 `json:"grade,omitempty" db:"grade"`
|
|
Percentage *float64 `json:"percentage,omitempty" db:"percentage"`
|
|
Notes string `json:"notes,omitempty" db:"notes"`
|
|
IsAbsent bool `json:"is_absent" db:"is_absent"`
|
|
NeedsRewrite bool `json:"needs_rewrite" db:"needs_rewrite"`
|
|
ApprovedByTeacher bool `json:"approved_by_teacher" db:"approved_by_teacher"`
|
|
ApprovedAt *time.Time `json:"approved_at,omitempty" db:"approved_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
|
|
// Joined fields
|
|
StudentName string `json:"student_name,omitempty"`
|
|
}
|
|
|
|
// GradeOverview represents aggregated grades for a student
|
|
type GradeOverview struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
StudentID uuid.UUID `json:"student_id" db:"student_id"`
|
|
SubjectID uuid.UUID `json:"subject_id" db:"subject_id"`
|
|
SchoolYearID uuid.UUID `json:"school_year_id" db:"school_year_id"`
|
|
Semester int `json:"semester" db:"semester"`
|
|
WrittenGradeAvg *float64 `json:"written_grade_avg,omitempty" db:"written_grade_avg"`
|
|
WrittenGradeCount int `json:"written_grade_count" db:"written_grade_count"`
|
|
OralGrade *float64 `json:"oral_grade,omitempty" db:"oral_grade"`
|
|
OralNotes string `json:"oral_notes,omitempty" db:"oral_notes"`
|
|
FinalGrade *float64 `json:"final_grade,omitempty" db:"final_grade"`
|
|
FinalGradeLocked bool `json:"final_grade_locked" db:"final_grade_locked"`
|
|
WrittenWeight int `json:"written_weight" db:"written_weight"`
|
|
OralWeight int `json:"oral_weight" db:"oral_weight"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
|
|
// Joined fields
|
|
StudentName string `json:"student_name,omitempty"`
|
|
SubjectName string `json:"subject_name,omitempty"`
|
|
}
|
|
|
|
// AttendanceStatus represents attendance status
|
|
type AttendanceStatus string
|
|
|
|
const (
|
|
AttendancePresent AttendanceStatus = "present"
|
|
AttendanceAbsentExcused AttendanceStatus = "absent_excused"
|
|
AttendanceAbsentUnexcused AttendanceStatus = "absent_unexcused"
|
|
AttendanceLate AttendanceStatus = "late"
|
|
)
|
|
|
|
// Attendance represents a student's attendance record
|
|
type Attendance struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
StudentID uuid.UUID `json:"student_id" db:"student_id"`
|
|
Date time.Time `json:"date" db:"date"`
|
|
Status AttendanceStatus `json:"status" db:"status"`
|
|
Periods int `json:"periods" db:"periods"`
|
|
Reason string `json:"reason,omitempty" db:"reason"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
// Joined fields
|
|
StudentName string `json:"student_name,omitempty"`
|
|
}
|
|
|
|
// GradebookEntryType represents types of gradebook entries
|
|
type GradebookEntryType string
|
|
|
|
const (
|
|
EntryTypeNote GradebookEntryType = "note"
|
|
EntryTypeWarning GradebookEntryType = "warning"
|
|
EntryTypePraise GradebookEntryType = "praise"
|
|
EntryTypeIncident GradebookEntryType = "incident"
|
|
EntryTypeHomework GradebookEntryType = "homework"
|
|
)
|
|
|
|
// GradebookEntry represents a gradebook entry
|
|
type GradebookEntry struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
ClassID uuid.UUID `json:"class_id" db:"class_id"`
|
|
StudentID *uuid.UUID `json:"student_id,omitempty" db:"student_id"`
|
|
Date time.Time `json:"date" db:"date"`
|
|
EntryType GradebookEntryType `json:"entry_type" db:"entry_type"`
|
|
Content string `json:"content" db:"content"`
|
|
IsVisibleToParents bool `json:"is_visible_to_parents" db:"is_visible_to_parents"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
// Joined fields
|
|
StudentName string `json:"student_name,omitempty"`
|
|
}
|
|
|
|
// CertificateStatus represents certificate status
|
|
type CertificateStatus string
|
|
|
|
const (
|
|
CertificateStatusDraft CertificateStatus = "draft"
|
|
CertificateStatusFinal CertificateStatus = "final"
|
|
CertificateStatusPrinted CertificateStatus = "printed"
|
|
)
|
|
|
|
// CertificateType represents types of certificates
|
|
type CertificateType string
|
|
|
|
const (
|
|
CertificateTypeHalbjahr CertificateType = "halbjahr"
|
|
CertificateTypeJahres CertificateType = "jahres"
|
|
CertificateTypeAbschluss CertificateType = "abschluss"
|
|
)
|
|
|
|
// Certificate represents a student certificate
|
|
type Certificate struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
StudentID uuid.UUID `json:"student_id" db:"student_id"`
|
|
SchoolYearID uuid.UUID `json:"school_year_id" db:"school_year_id"`
|
|
Semester int `json:"semester" db:"semester"`
|
|
CertificateType CertificateType `json:"certificate_type" db:"certificate_type"`
|
|
TemplateName string `json:"template_name,omitempty" db:"template_name"`
|
|
GradesJSON map[string]any `json:"grades_json,omitempty" db:"grades_json"`
|
|
Remarks string `json:"remarks,omitempty" db:"remarks"`
|
|
AbsenceDays int `json:"absence_days" db:"absence_days"`
|
|
AbsenceDaysUnexcused int `json:"absence_days_unexcused" db:"absence_days_unexcused"`
|
|
GeneratedPDFPath string `json:"generated_pdf_path,omitempty" db:"generated_pdf_path"`
|
|
Status CertificateStatus `json:"status" db:"status"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
|
|
// Joined fields
|
|
StudentName string `json:"student_name,omitempty"`
|
|
ClassName string `json:"class_name,omitempty"`
|
|
}
|
|
|
|
// Request/Response DTOs
|
|
|
|
// CreateSchoolYearRequest represents a request to create a school year
|
|
type CreateSchoolYearRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
StartDate string `json:"start_date" binding:"required"`
|
|
EndDate string `json:"end_date" binding:"required"`
|
|
IsCurrent bool `json:"is_current"`
|
|
}
|
|
|
|
// CreateClassRequest represents a request to create a class
|
|
type CreateClassRequest struct {
|
|
SchoolYearID string `json:"school_year_id"`
|
|
Name string `json:"name" binding:"required"`
|
|
GradeLevel int `json:"grade_level" binding:"required,min=1,max=13"`
|
|
SchoolType string `json:"school_type"`
|
|
FederalState string `json:"federal_state"`
|
|
}
|
|
|
|
// CreateStudentRequest represents a request to create a student
|
|
type CreateStudentRequest struct {
|
|
FirstName string `json:"first_name" binding:"required"`
|
|
LastName string `json:"last_name" binding:"required"`
|
|
BirthDate string `json:"birth_date"`
|
|
StudentNumber string `json:"student_number"`
|
|
Notes string `json:"notes"`
|
|
}
|
|
|
|
// CreateSubjectRequest represents a request to create a subject
|
|
type CreateSubjectRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
ShortName string `json:"short_name"`
|
|
IsMainSubject bool `json:"is_main_subject"`
|
|
}
|
|
|
|
// CreateExamRequest represents a request to create an exam
|
|
type CreateExamRequest struct {
|
|
ClassID string `json:"class_id"`
|
|
SubjectID string `json:"subject_id"`
|
|
Title string `json:"title" binding:"required"`
|
|
ExamType ExamType `json:"exam_type" binding:"required"`
|
|
Topic string `json:"topic"`
|
|
Content string `json:"content"`
|
|
DifficultyLevel int `json:"difficulty_level"`
|
|
DurationMinutes int `json:"duration_minutes"`
|
|
MaxPoints float64 `json:"max_points"`
|
|
ExamDate string `json:"exam_date"`
|
|
}
|
|
|
|
// UpdateExamResultRequest represents a request to update exam results
|
|
type UpdateExamResultRequest struct {
|
|
StudentID string `json:"student_id" binding:"required"`
|
|
PointsAchieved *float64 `json:"points_achieved"`
|
|
Grade *float64 `json:"grade"`
|
|
Notes string `json:"notes"`
|
|
IsAbsent bool `json:"is_absent"`
|
|
NeedsRewrite bool `json:"needs_rewrite"`
|
|
}
|
|
|
|
// UpdateOralGradeRequest represents a request to update oral grades
|
|
type UpdateOralGradeRequest struct {
|
|
OralGrade float64 `json:"oral_grade" binding:"required,min=1,max=6"`
|
|
OralNotes string `json:"oral_notes"`
|
|
}
|
|
|
|
// CreateAttendanceRequest represents a request to create attendance
|
|
type CreateAttendanceRequest struct {
|
|
StudentID string `json:"student_id" binding:"required"`
|
|
Date string `json:"date" binding:"required"`
|
|
Status AttendanceStatus `json:"status" binding:"required"`
|
|
Periods int `json:"periods"`
|
|
Reason string `json:"reason"`
|
|
}
|
|
|
|
// CreateGradebookEntryRequest represents a request to create a gradebook entry
|
|
type CreateGradebookEntryRequest struct {
|
|
ClassID string `json:"class_id" binding:"required"`
|
|
StudentID string `json:"student_id"`
|
|
Date string `json:"date" binding:"required"`
|
|
EntryType GradebookEntryType `json:"entry_type" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
IsVisibleToParents bool `json:"is_visible_to_parents"`
|
|
}
|
|
|
|
// GenerateCertificateRequest represents a request to generate a certificate
|
|
type GenerateCertificateRequest struct {
|
|
StudentID string `json:"student_id" binding:"required"`
|
|
SchoolYearID string `json:"school_year_id" binding:"required"`
|
|
Semester int `json:"semester" binding:"required,min=1,max=2"`
|
|
CertificateType CertificateType `json:"certificate_type" binding:"required"`
|
|
TemplateName string `json:"template_name"`
|
|
Remarks string `json:"remarks"`
|
|
}
|
|
|
|
// GenerateExamVariantRequest represents a request to generate an exam variant
|
|
type GenerateExamVariantRequest struct {
|
|
VariationType string `json:"variation_type" binding:"required"` // "rewrite", "alternative", "similar"
|
|
}
|