Files
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

237 lines
8.0 KiB
Go

package services
import (
"context"
"time"
"github.com/breakpilot/school-service/internal/models"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
// ClassService handles class-related operations
type ClassService struct {
db *pgxpool.Pool
}
// NewClassService creates a new ClassService
func NewClassService(db *pgxpool.Pool) *ClassService {
return &ClassService{db: db}
}
// School Year Operations
// CreateSchoolYear creates a new school year
func (s *ClassService) CreateSchoolYear(ctx context.Context, teacherID string, req *models.CreateSchoolYearRequest) (*models.SchoolYear, error) {
startDate, _ := time.Parse("2006-01-02", req.StartDate)
endDate, _ := time.Parse("2006-01-02", req.EndDate)
// If this is current, unset other current years for this teacher
if req.IsCurrent {
s.db.Exec(ctx, `UPDATE school_years SET is_current = false WHERE teacher_id = $1`, teacherID)
}
var year models.SchoolYear
err := s.db.QueryRow(ctx, `
INSERT INTO school_years (teacher_id, name, start_date, end_date, is_current)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, name, start_date, end_date, is_current, teacher_id, created_at
`, teacherID, req.Name, startDate, endDate, req.IsCurrent).Scan(
&year.ID, &year.Name, &year.StartDate, &year.EndDate, &year.IsCurrent, &year.TeacherID, &year.CreatedAt,
)
return &year, err
}
// GetSchoolYears returns all school years for a teacher
func (s *ClassService) GetSchoolYears(ctx context.Context, teacherID string) ([]models.SchoolYear, error) {
rows, err := s.db.Query(ctx, `
SELECT id, name, start_date, end_date, is_current, teacher_id, created_at
FROM school_years
WHERE teacher_id = $1
ORDER BY start_date DESC
`, teacherID)
if err != nil {
return nil, err
}
defer rows.Close()
var years []models.SchoolYear
for rows.Next() {
var y models.SchoolYear
if err := rows.Scan(&y.ID, &y.Name, &y.StartDate, &y.EndDate, &y.IsCurrent, &y.TeacherID, &y.CreatedAt); err != nil {
return nil, err
}
years = append(years, y)
}
return years, nil
}
// Class Operations
// CreateClass creates a new class
func (s *ClassService) CreateClass(ctx context.Context, teacherID string, req *models.CreateClassRequest) (*models.Class, error) {
var schoolYearID *uuid.UUID
if req.SchoolYearID != "" {
id, _ := uuid.Parse(req.SchoolYearID)
schoolYearID = &id
}
var class models.Class
err := s.db.QueryRow(ctx, `
INSERT INTO classes (teacher_id, school_year_id, name, grade_level, school_type, federal_state)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, teacher_id, school_year_id, name, grade_level, school_type, federal_state, created_at
`, teacherID, schoolYearID, req.Name, req.GradeLevel, req.SchoolType, req.FederalState).Scan(
&class.ID, &class.TeacherID, &class.SchoolYearID, &class.Name, &class.GradeLevel, &class.SchoolType, &class.FederalState, &class.CreatedAt,
)
return &class, err
}
// GetClasses returns all classes for a teacher
func (s *ClassService) GetClasses(ctx context.Context, teacherID string) ([]models.Class, error) {
rows, err := s.db.Query(ctx, `
SELECT c.id, c.teacher_id, c.school_year_id, c.name, c.grade_level, c.school_type, c.federal_state, c.created_at,
COALESCE((SELECT COUNT(*) FROM students WHERE class_id = c.id), 0) as student_count
FROM classes c
WHERE c.teacher_id = $1
ORDER BY c.grade_level, c.name
`, teacherID)
if err != nil {
return nil, err
}
defer rows.Close()
var classes []models.Class
for rows.Next() {
var c models.Class
if err := rows.Scan(&c.ID, &c.TeacherID, &c.SchoolYearID, &c.Name, &c.GradeLevel, &c.SchoolType, &c.FederalState, &c.CreatedAt, &c.StudentCount); err != nil {
return nil, err
}
classes = append(classes, c)
}
return classes, nil
}
// GetClass returns a single class
func (s *ClassService) GetClass(ctx context.Context, classID, teacherID string) (*models.Class, error) {
var class models.Class
err := s.db.QueryRow(ctx, `
SELECT c.id, c.teacher_id, c.school_year_id, c.name, c.grade_level, c.school_type, c.federal_state, c.created_at,
COALESCE((SELECT COUNT(*) FROM students WHERE class_id = c.id), 0) as student_count
FROM classes c
WHERE c.id = $1 AND c.teacher_id = $2
`, classID, teacherID).Scan(
&class.ID, &class.TeacherID, &class.SchoolYearID, &class.Name, &class.GradeLevel, &class.SchoolType, &class.FederalState, &class.CreatedAt, &class.StudentCount,
)
return &class, err
}
// DeleteClass deletes a class
func (s *ClassService) DeleteClass(ctx context.Context, classID, teacherID string) error {
_, err := s.db.Exec(ctx, `DELETE FROM classes WHERE id = $1 AND teacher_id = $2`, classID, teacherID)
return err
}
// Student Operations
// CreateStudent creates a new student
func (s *ClassService) CreateStudent(ctx context.Context, classID string, req *models.CreateStudentRequest) (*models.Student, error) {
var birthDate *time.Time
if req.BirthDate != "" {
t, _ := time.Parse("2006-01-02", req.BirthDate)
birthDate = &t
}
// Get school_id from class
var schoolID string
err := s.db.QueryRow(ctx, `SELECT school_id FROM classes WHERE id = $1`, classID).Scan(&schoolID)
if err != nil {
return nil, err
}
var student models.Student
err = s.db.QueryRow(ctx, `
INSERT INTO students (school_id, class_id, first_name, last_name, date_of_birth, student_number)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, class_id, first_name, last_name, date_of_birth, student_number, created_at
`, schoolID, classID, req.FirstName, req.LastName, birthDate, req.StudentNumber).Scan(
&student.ID, &student.ClassID, &student.FirstName, &student.LastName, &student.BirthDate, &student.StudentNumber, &student.CreatedAt,
)
return &student, err
}
// GetStudents returns all students in a class
func (s *ClassService) GetStudents(ctx context.Context, classID string) ([]models.Student, error) {
rows, err := s.db.Query(ctx, `
SELECT id, class_id, first_name, last_name, date_of_birth, student_number, created_at
FROM students
WHERE class_id = $1
ORDER BY last_name, first_name
`, classID)
if err != nil {
return nil, err
}
defer rows.Close()
var students []models.Student
for rows.Next() {
var st models.Student
if err := rows.Scan(&st.ID, &st.ClassID, &st.FirstName, &st.LastName, &st.BirthDate, &st.StudentNumber, &st.CreatedAt); err != nil {
return nil, err
}
students = append(students, st)
}
return students, nil
}
// DeleteStudent deletes a student
func (s *ClassService) DeleteStudent(ctx context.Context, studentID string) error {
_, err := s.db.Exec(ctx, `DELETE FROM students WHERE id = $1`, studentID)
return err
}
// Subject Operations
// CreateSubject creates a new subject
func (s *ClassService) CreateSubject(ctx context.Context, teacherID string, req *models.CreateSubjectRequest) (*models.Subject, error) {
var subject models.Subject
err := s.db.QueryRow(ctx, `
INSERT INTO subjects (teacher_id, name, short_name, is_main_subject)
VALUES ($1, $2, $3, $4)
RETURNING id, teacher_id, name, short_name, is_main_subject, created_at
`, teacherID, req.Name, req.ShortName, req.IsMainSubject).Scan(
&subject.ID, &subject.TeacherID, &subject.Name, &subject.ShortName, &subject.IsMainSubject, &subject.CreatedAt,
)
return &subject, err
}
// GetSubjects returns all subjects for a teacher
func (s *ClassService) GetSubjects(ctx context.Context, teacherID string) ([]models.Subject, error) {
rows, err := s.db.Query(ctx, `
SELECT id, teacher_id, name, short_name, is_main_subject, created_at
FROM subjects
WHERE teacher_id = $1
ORDER BY name
`, teacherID)
if err != nil {
return nil, err
}
defer rows.Close()
var subjects []models.Subject
for rows.Next() {
var subj models.Subject
if err := rows.Scan(&subj.ID, &subj.TeacherID, &subj.Name, &subj.ShortName, &subj.IsMainSubject, &subj.CreatedAt); err != nil {
return nil, err
}
subjects = append(subjects, subj)
}
return subjects, nil
}
// DeleteSubject deletes a subject
func (s *ClassService) DeleteSubject(ctx context.Context, subjectID, teacherID string) error {
_, err := s.db.Exec(ctx, `DELETE FROM subjects WHERE id = $1 AND teacher_id = $2`, subjectID, teacherID)
return err
}