package models import ( "time" "github.com/google/uuid" ) // ======================================== // Stundenplan / Timetable // ======================================== // TimetableSlot represents a time slot in the timetable type TimetableSlot struct { ID uuid.UUID `json:"id" db:"id"` SchoolID uuid.UUID `json:"school_id" db:"school_id"` SlotNumber int `json:"slot_number" db:"slot_number"` // 1, 2, 3... (Stunde) StartTime string `json:"start_time" db:"start_time"` // "08:00" EndTime string `json:"end_time" db:"end_time"` // "08:45" IsBreak bool `json:"is_break" db:"is_break"` // Pause Name *string `json:"name,omitempty" db:"name"` // e.g., "1. Stunde", "Große Pause" } // TimetableEntry represents a single lesson in the timetable type TimetableEntry struct { ID uuid.UUID `json:"id" db:"id"` SchoolYearID uuid.UUID `json:"school_year_id" db:"school_year_id"` ClassID uuid.UUID `json:"class_id" db:"class_id"` SubjectID uuid.UUID `json:"subject_id" db:"subject_id"` TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"` SlotID uuid.UUID `json:"slot_id" db:"slot_id"` DayOfWeek int `json:"day_of_week" db:"day_of_week"` // 1=Monday, 5=Friday Room *string `json:"room,omitempty" db:"room"` ValidFrom time.Time `json:"valid_from" db:"valid_from"` ValidUntil *time.Time `json:"valid_until,omitempty" db:"valid_until"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // TimetableSubstitution represents a substitution/replacement lesson type TimetableSubstitution struct { ID uuid.UUID `json:"id" db:"id"` OriginalEntryID uuid.UUID `json:"original_entry_id" db:"original_entry_id"` Date time.Time `json:"date" db:"date"` SubstituteTeacherID *uuid.UUID `json:"substitute_teacher_id,omitempty" db:"substitute_teacher_id"` SubstituteSubjectID *uuid.UUID `json:"substitute_subject_id,omitempty" db:"substitute_subject_id"` Room *string `json:"room,omitempty" db:"room"` Type string `json:"type" db:"type"` // 'substitution', 'cancelled', 'room_change', 'supervision' Note *string `json:"note,omitempty" db:"note"` CreatedAt time.Time `json:"created_at" db:"created_at"` CreatedBy uuid.UUID `json:"created_by" db:"created_by"` } // ======================================== // Abwesenheit / Attendance // ======================================== // AttendanceRecord represents a student's attendance for a specific lesson type AttendanceRecord struct { ID uuid.UUID `json:"id" db:"id"` StudentID uuid.UUID `json:"student_id" db:"student_id"` TimetableEntryID *uuid.UUID `json:"timetable_entry_id,omitempty" db:"timetable_entry_id"` Date time.Time `json:"date" db:"date"` SlotID uuid.UUID `json:"slot_id" db:"slot_id"` Status string `json:"status" db:"status"` // AttendanceStatus constants RecordedBy uuid.UUID `json:"recorded_by" db:"recorded_by"` Note *string `json:"note,omitempty" db:"note"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // AbsenceReport represents a full absence report (one or more days) type AbsenceReport struct { ID uuid.UUID `json:"id" db:"id"` StudentID uuid.UUID `json:"student_id" db:"student_id"` StartDate time.Time `json:"start_date" db:"start_date"` EndDate time.Time `json:"end_date" db:"end_date"` Reason *string `json:"reason,omitempty" db:"reason"` ReasonCategory string `json:"reason_category" db:"reason_category"` Status string `json:"status" db:"status"` ReportedBy uuid.UUID `json:"reported_by" db:"reported_by"` ReportedAt time.Time `json:"reported_at" db:"reported_at"` ConfirmedBy *uuid.UUID `json:"confirmed_by,omitempty" db:"confirmed_by"` ConfirmedAt *time.Time `json:"confirmed_at,omitempty" db:"confirmed_at"` MedicalCertificate bool `json:"medical_certificate" db:"medical_certificate"` CertificateUploaded bool `json:"certificate_uploaded" db:"certificate_uploaded"` MatrixNotificationSent bool `json:"matrix_notification_sent" db:"matrix_notification_sent"` EmailNotificationSent bool `json:"email_notification_sent" db:"email_notification_sent"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // AbsenceNotification tracks notifications sent to parents about absences type AbsenceNotification struct { ID uuid.UUID `json:"id" db:"id"` AttendanceRecordID uuid.UUID `json:"attendance_record_id" db:"attendance_record_id"` ParentID uuid.UUID `json:"parent_id" db:"parent_id"` Channel string `json:"channel" db:"channel"` MessageContent string `json:"message_content" db:"message_content"` SentAt *time.Time `json:"sent_at,omitempty" db:"sent_at"` ReadAt *time.Time `json:"read_at,omitempty" db:"read_at"` ResponseReceived bool `json:"response_received" db:"response_received"` ResponseContent *string `json:"response_content,omitempty" db:"response_content"` ResponseAt *time.Time `json:"response_at,omitempty" db:"response_at"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // ======================================== // Notenspiegel / Grades // ======================================== // GradeScale represents the grading scale used type GradeScale struct { ID uuid.UUID `json:"id" db:"id"` SchoolID uuid.UUID `json:"school_id" db:"school_id"` Name string `json:"name" db:"name"` MinValue float64 `json:"min_value" db:"min_value"` MaxValue float64 `json:"max_value" db:"max_value"` PassingValue float64 `json:"passing_value" db:"passing_value"` IsAscending bool `json:"is_ascending" db:"is_ascending"` IsDefault bool `json:"is_default" db:"is_default"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // Grade represents a single grade for a student type Grade 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"` TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"` SchoolYearID uuid.UUID `json:"school_year_id" db:"school_year_id"` GradeScaleID uuid.UUID `json:"grade_scale_id" db:"grade_scale_id"` Type string `json:"type" db:"type"` Value float64 `json:"value" db:"value"` Weight float64 `json:"weight" db:"weight"` Date time.Time `json:"date" db:"date"` Title *string `json:"title,omitempty" db:"title"` Description *string `json:"description,omitempty" db:"description"` IsVisible bool `json:"is_visible" db:"is_visible"` Semester int `json:"semester" db:"semester"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // GradeComment represents a teacher comment on a student's grade type GradeComment struct { ID uuid.UUID `json:"id" db:"id"` GradeID uuid.UUID `json:"grade_id" db:"grade_id"` TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"` Comment string `json:"comment" db:"comment"` IsPrivate bool `json:"is_private" db:"is_private"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // ======================================== // Klassenbuch, Meetings, Communication // ======================================== // ClassDiaryEntry represents an entry in the digital class diary type ClassDiaryEntry struct { ID uuid.UUID `json:"id" db:"id"` ClassID uuid.UUID `json:"class_id" db:"class_id"` Date time.Time `json:"date" db:"date"` SlotID uuid.UUID `json:"slot_id" db:"slot_id"` SubjectID uuid.UUID `json:"subject_id" db:"subject_id"` TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"` Topic *string `json:"topic,omitempty" db:"topic"` Homework *string `json:"homework,omitempty" db:"homework"` HomeworkDueDate *time.Time `json:"homework_due_date,omitempty" db:"homework_due_date"` Materials *string `json:"materials,omitempty" db:"materials"` Notes *string `json:"notes,omitempty" db:"notes"` IsCancelled bool `json:"is_cancelled" db:"is_cancelled"` CancellationReason *string `json:"cancellation_reason,omitempty" db:"cancellation_reason"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // ParentMeetingSlot represents available time slots for parent meetings type ParentMeetingSlot struct { ID uuid.UUID `json:"id" db:"id"` TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"` Date time.Time `json:"date" db:"date"` StartTime string `json:"start_time" db:"start_time"` EndTime string `json:"end_time" db:"end_time"` Location *string `json:"location,omitempty" db:"location"` IsOnline bool `json:"is_online" db:"is_online"` MeetingLink *string `json:"meeting_link,omitempty" db:"meeting_link"` IsBooked bool `json:"is_booked" db:"is_booked"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // ParentMeeting represents a booked parent-teacher meeting type ParentMeeting struct { ID uuid.UUID `json:"id" db:"id"` SlotID uuid.UUID `json:"slot_id" db:"slot_id"` ParentID uuid.UUID `json:"parent_id" db:"parent_id"` StudentID uuid.UUID `json:"student_id" db:"student_id"` Topic *string `json:"topic,omitempty" db:"topic"` Notes *string `json:"notes,omitempty" db:"notes"` Status string `json:"status" db:"status"` CancelledAt *time.Time `json:"cancelled_at,omitempty" db:"cancelled_at"` CancelledBy *uuid.UUID `json:"cancelled_by,omitempty" db:"cancelled_by"` CancelReason *string `json:"cancel_reason,omitempty" db:"cancel_reason"` CompletedAt *time.Time `json:"completed_at,omitempty" db:"completed_at"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // MatrixRoom tracks Matrix rooms created for school communication type MatrixRoom struct { ID uuid.UUID `json:"id" db:"id"` SchoolID uuid.UUID `json:"school_id" db:"school_id"` MatrixRoomID string `json:"matrix_room_id" db:"matrix_room_id"` Type string `json:"type" db:"type"` ClassID *uuid.UUID `json:"class_id,omitempty" db:"class_id"` StudentID *uuid.UUID `json:"student_id,omitempty" db:"student_id"` Name string `json:"name" db:"name"` IsEncrypted bool `json:"is_encrypted" db:"is_encrypted"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // MatrixRoomMember tracks membership in Matrix rooms type MatrixRoomMember struct { ID uuid.UUID `json:"id" db:"id"` MatrixRoomID uuid.UUID `json:"matrix_room_id" db:"matrix_room_id"` MatrixUserID string `json:"matrix_user_id" db:"matrix_user_id"` UserID *uuid.UUID `json:"user_id,omitempty" db:"user_id"` PowerLevel int `json:"power_level" db:"power_level"` CanWrite bool `json:"can_write" db:"can_write"` JoinedAt time.Time `json:"joined_at" db:"joined_at"` LeftAt *time.Time `json:"left_at,omitempty" db:"left_at"` } // ParentOnboardingToken for QR-code based parent onboarding type ParentOnboardingToken struct { ID uuid.UUID `json:"id" db:"id"` SchoolID uuid.UUID `json:"school_id" db:"school_id"` ClassID uuid.UUID `json:"class_id" db:"class_id"` StudentID uuid.UUID `json:"student_id" db:"student_id"` Token string `json:"token" db:"token"` Role string `json:"role" db:"role"` ExpiresAt time.Time `json:"expires_at" db:"expires_at"` UsedAt *time.Time `json:"used_at,omitempty" db:"used_at"` UsedByUserID *uuid.UUID `json:"used_by_user_id,omitempty" db:"used_by_user_id"` CreatedAt time.Time `json:"created_at" db:"created_at"` CreatedBy uuid.UUID `json:"created_by" db:"created_by"` } // ======================================== // Schulverwaltung DTOs // ======================================== // CreateSchoolRequest for creating a new school type CreateSchoolRequest struct { Name string `json:"name" binding:"required"` ShortName *string `json:"short_name"` Type string `json:"type" binding:"required"` Address *string `json:"address"` City *string `json:"city"` PostalCode *string `json:"postal_code"` State *string `json:"state"` Phone *string `json:"phone"` Email *string `json:"email"` Website *string `json:"website"` } // CreateClassRequest for creating a new class type CreateClassRequest struct { SchoolYearID string `json:"school_year_id" binding:"required"` Name string `json:"name" binding:"required"` Grade int `json:"grade" binding:"required"` Section *string `json:"section"` Room *string `json:"room"` } // CreateStudentRequest for creating a new student type CreateStudentRequest struct { ClassID string `json:"class_id" binding:"required"` StudentNumber *string `json:"student_number"` FirstName string `json:"first_name" binding:"required"` LastName string `json:"last_name" binding:"required"` DateOfBirth *string `json:"date_of_birth"` // ISO 8601 Gender *string `json:"gender"` } // RecordAttendanceRequest for recording attendance type RecordAttendanceRequest struct { StudentID string `json:"student_id" binding:"required"` Date string `json:"date" binding:"required"` // ISO 8601 SlotID string `json:"slot_id" binding:"required"` Status string `json:"status" binding:"required"` // AttendanceStatus Note *string `json:"note"` } // ReportAbsenceRequest for parents reporting absence type ReportAbsenceRequest struct { StudentID string `json:"student_id" binding:"required"` StartDate string `json:"start_date" binding:"required"` EndDate string `json:"end_date" binding:"required"` Reason *string `json:"reason"` ReasonCategory string `json:"reason_category" binding:"required"` } // CreateGradeRequest for creating a grade type CreateGradeRequest struct { StudentID string `json:"student_id" binding:"required"` SubjectID string `json:"subject_id" binding:"required"` SchoolYearID string `json:"school_year_id" binding:"required"` Type string `json:"type" binding:"required"` Value float64 `json:"value" binding:"required"` Weight float64 `json:"weight"` Date string `json:"date" binding:"required"` Title *string `json:"title"` Description *string `json:"description"` Semester int `json:"semester" binding:"required"` } // StudentGradeOverview provides a summary of all grades for a student in a subject type StudentGradeOverview struct { Student Student `json:"student"` Subject Subject `json:"subject"` Grades []Grade `json:"grades"` Average float64 `json:"average"` OralAverage float64 `json:"oral_average"` ExamAverage float64 `json:"exam_average"` Semester int `json:"semester"` } // ClassAttendanceOverview provides attendance summary for a class type ClassAttendanceOverview struct { Class Class `json:"class"` Date time.Time `json:"date"` TotalStudents int `json:"total_students"` PresentCount int `json:"present_count"` AbsentCount int `json:"absent_count"` LateCount int `json:"late_count"` Records []AttendanceRecord `json:"records"` } // ParentDashboard provides a parent's view of their children's data type ParentDashboard struct { Children []StudentOverview `json:"children"` UnreadMessages int `json:"unread_messages"` UpcomingMeetings []ParentMeeting `json:"upcoming_meetings"` RecentGrades []Grade `json:"recent_grades"` PendingActions []string `json:"pending_actions"` } // StudentOverview provides summary info about a student type StudentOverview struct { Student Student `json:"student"` Class Class `json:"class"` ClassTeacher *Teacher `json:"class_teacher,omitempty"` AttendanceRate float64 `json:"attendance_rate"` UnexcusedAbsences int `json:"unexcused_absences"` GradeAverage float64 `json:"grade_average"` } // TimetableView provides a formatted timetable for display type TimetableView struct { Class Class `json:"class"` Week string `json:"week"` // ISO week: "2025-W01" Days []TimetableDayView `json:"days"` } // TimetableDayView represents a single day in the timetable type TimetableDayView struct { Date time.Time `json:"date"` DayName string `json:"day_name"` Lessons []TimetableLessonView `json:"lessons"` } // TimetableLessonView represents a single lesson in the timetable view type TimetableLessonView struct { Slot TimetableSlot `json:"slot"` Subject *Subject `json:"subject,omitempty"` Teacher *Teacher `json:"teacher,omitempty"` Room *string `json:"room,omitempty"` IsSubstitution bool `json:"is_substitution"` IsCancelled bool `json:"is_cancelled"` Note *string `json:"note,omitempty"` }