[split-required] [guardrail-change] Enforce 500 LOC budget across all services
Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook) and split all 44 files exceeding 500 LOC into domain-focused modules: - consent-service (Go): models, handlers, services, database splits - backend-core (Python): security_api, rbac_api, pdf_service, auth splits - admin-core (TypeScript): 5 page.tsx + sidebar extractions - pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits - voice-service (Python): enhanced_task_orchestrator split Result: 0 violations, 36 exempted (pipeline, tests, pure-data files). Go build verified clean. No behavior changes — pure structural splits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
182
consent-service/internal/database/migrate_school.go
Normal file
182
consent-service/internal/database/migrate_school.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// migrateSchool creates school management tables: schools, classes,
|
||||
// students, teachers, parents, timetable, attendance, grades,
|
||||
// class diary, parent meetings, Matrix integration (Phase 9).
|
||||
func migrateSchool(db *DB) error {
|
||||
ctx := context.Background()
|
||||
|
||||
migrations := []string{
|
||||
// =============================================
|
||||
// Phase 9: Schulverwaltung / School Management
|
||||
// Matrix-basierte Kommunikation für Schulen
|
||||
// =============================================
|
||||
|
||||
// Schools table
|
||||
`CREATE TABLE IF NOT EXISTS schools (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
short_name VARCHAR(50),
|
||||
type VARCHAR(50) NOT NULL,
|
||||
address TEXT,
|
||||
city VARCHAR(100),
|
||||
postal_code VARCHAR(20),
|
||||
state VARCHAR(50),
|
||||
country VARCHAR(2) DEFAULT 'DE',
|
||||
phone VARCHAR(50),
|
||||
email VARCHAR(255),
|
||||
website VARCHAR(255),
|
||||
matrix_server_name VARCHAR(255),
|
||||
logo_url TEXT,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)`,
|
||||
|
||||
// School years
|
||||
`CREATE TABLE IF NOT EXISTS school_years (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
school_id UUID NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
||||
name VARCHAR(20) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
is_current BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(school_id, name)
|
||||
)`,
|
||||
|
||||
// Subjects
|
||||
`CREATE TABLE IF NOT EXISTS subjects (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
school_id UUID NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
short_name VARCHAR(10) NOT NULL,
|
||||
color VARCHAR(7),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(school_id, short_name)
|
||||
)`,
|
||||
|
||||
// Classes
|
||||
`CREATE TABLE IF NOT EXISTS classes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
school_id UUID NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
||||
school_year_id UUID NOT NULL REFERENCES school_years(id) ON DELETE CASCADE,
|
||||
name VARCHAR(20) NOT NULL,
|
||||
grade INT NOT NULL,
|
||||
section VARCHAR(5),
|
||||
room VARCHAR(50),
|
||||
matrix_info_room VARCHAR(255),
|
||||
matrix_rep_room VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(school_id, school_year_id, name)
|
||||
)`,
|
||||
|
||||
// Students
|
||||
`CREATE TABLE IF NOT EXISTS students (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
school_id UUID NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
||||
class_id UUID NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
||||
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
student_number VARCHAR(50),
|
||||
first_name VARCHAR(100) NOT NULL,
|
||||
last_name VARCHAR(100) NOT NULL,
|
||||
date_of_birth DATE,
|
||||
gender VARCHAR(1),
|
||||
matrix_user_id VARCHAR(255),
|
||||
matrix_dm_room VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)`,
|
||||
|
||||
// Teachers
|
||||
`CREATE TABLE IF NOT EXISTS teachers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
school_id UUID NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
teacher_code VARCHAR(10),
|
||||
title VARCHAR(20),
|
||||
first_name VARCHAR(100) NOT NULL,
|
||||
last_name VARCHAR(100) NOT NULL,
|
||||
matrix_user_id VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(school_id, user_id)
|
||||
)`,
|
||||
|
||||
// Class teachers assignment
|
||||
`CREATE TABLE IF NOT EXISTS class_teachers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
class_id UUID NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
||||
teacher_id UUID NOT NULL REFERENCES teachers(id) ON DELETE CASCADE,
|
||||
is_primary BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(class_id, teacher_id)
|
||||
)`,
|
||||
|
||||
// Teacher subjects assignment
|
||||
`CREATE TABLE IF NOT EXISTS teacher_subjects (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
teacher_id UUID NOT NULL REFERENCES teachers(id) ON DELETE CASCADE,
|
||||
subject_id UUID NOT NULL REFERENCES subjects(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(teacher_id, subject_id)
|
||||
)`,
|
||||
|
||||
// Parents
|
||||
`CREATE TABLE IF NOT EXISTS parents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
matrix_user_id VARCHAR(255),
|
||||
first_name VARCHAR(100) NOT NULL,
|
||||
last_name VARCHAR(100) NOT NULL,
|
||||
phone VARCHAR(50),
|
||||
emergency_contact BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(user_id)
|
||||
)`,
|
||||
|
||||
// Student-parent relationships
|
||||
`CREATE TABLE IF NOT EXISTS student_parents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
student_id UUID NOT NULL REFERENCES students(id) ON DELETE CASCADE,
|
||||
parent_id UUID NOT NULL REFERENCES parents(id) ON DELETE CASCADE,
|
||||
relationship VARCHAR(20) NOT NULL,
|
||||
is_primary BOOLEAN DEFAULT FALSE,
|
||||
has_custody BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(student_id, parent_id)
|
||||
)`,
|
||||
|
||||
// Parent representatives
|
||||
`CREATE TABLE IF NOT EXISTS parent_representatives (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
class_id UUID NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
||||
parent_id UUID NOT NULL REFERENCES parents(id) ON DELETE CASCADE,
|
||||
role VARCHAR(20) NOT NULL,
|
||||
elected_at TIMESTAMPTZ NOT NULL,
|
||||
expires_at TIMESTAMPTZ,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)`,
|
||||
}
|
||||
|
||||
for _, migration := range migrations {
|
||||
if _, err := db.Pool.Exec(ctx, migration); err != nil {
|
||||
return fmt.Errorf("migrateSchool: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the second batch (timetable, attendance, grades, etc.)
|
||||
return migrateSchoolPart2(db)
|
||||
}
|
||||
Reference in New Issue
Block a user