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>
412 lines
21 KiB
Markdown
412 lines
21 KiB
Markdown
# Zeugnis-System - Architecture Documentation
|
|
|
|
## Overview
|
|
|
|
The Zeugnis (Certificate) System enables schools to generate official school certificates with grades, attendance data, and remarks. It extends the existing School-Service with comprehensive grade management and certificate generation workflows.
|
|
|
|
## Architecture Diagram
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ Python Backend (Port 8000) │
|
|
│ backend/frontend/modules/school.py │
|
|
│ │
|
|
│ ┌─────────────────────────────────┐ │
|
|
│ │ panel-school-certificates │ │
|
|
│ │ - Klassenauswahl │ │
|
|
│ │ - Notenspiegel │ │
|
|
│ │ - Zeugnis-Wizard (5 Steps) │ │
|
|
│ │ - Workflow-Status │ │
|
|
│ └─────────────────────────────────┘ │
|
|
└──────────────────┬──────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────────────────┐
|
|
│ School-Service (Go, Port 8084) │
|
|
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
|
|
│ │ Grade Handlers │ │ Statistics Handlers │ │ Certificate Handlers │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ GetClassGrades │ │ GetClassStatistics │ │ GetCertificateTemplates │ │
|
|
│ │ GetStudentGrades │ │ GetSubjectStatistics│ │ GetClassCertificates │ │
|
|
│ │ UpdateOralGrade │ │ GetStudentStatistics│ │ GenerateCertificate │ │
|
|
│ │ CalculateFinalGrades│ │ GetNotenspiegel │ │ BulkGenerateCertificates │ │
|
|
│ │ TransferApprovedGrades│ │ │ │ FinalizeCertificate │ │
|
|
│ │ LockFinalGrade │ │ │ │ GetCertificatePDF │ │
|
|
│ │ UpdateGradeWeights │ │ │ │ │ │
|
|
│ └─────────────────────┘ └─────────────────────┘ └─────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────────────────────┐│
|
|
│ │ Grade Service Layer ││
|
|
│ │ ││
|
|
│ │ - ClassStatistics struct (average, pass_rate, at_risk_count, grade_distribution) ││
|
|
│ │ - SubjectStatistics struct (class average, best/worst, exam results) ││
|
|
│ │ - StudentStatistics struct (overall average, subject performance) ││
|
|
│ │ - Notenspiegel struct (grade 1-6 distribution) ││
|
|
│ └─────────────────────────────────────────────────────────────────────────────────────┘│
|
|
└─────────────────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────┐
|
|
│ PostgreSQL Database │
|
|
│ │
|
|
│ Tables: │
|
|
│ - grade_overview │
|
|
│ - exam_results │
|
|
│ - students │
|
|
│ - classes │
|
|
│ - subjects │
|
|
│ - certificates │
|
|
│ - attendance │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
## Zeugnis Workflow (Role Chain)
|
|
|
|
The certificate workflow follows a strict approval chain from subject teachers to school principal:
|
|
|
|
```
|
|
┌──────────────────┐ ┌──────────────────┐ ┌────────────────────────┐ ┌────────────────────┐ ┌──────────────────┐
|
|
│ FACHLEHRER │───▶│ KLASSENLEHRER │───▶│ ZEUGNISBEAUFTRAGTER │───▶│ SCHULLEITUNG │───▶│ SEKRETARIAT │
|
|
│ (Subject │ │ (Class │ │ (Certificate │ │ (Principal) │ │ (Secretary) │
|
|
│ Teacher) │ │ Teacher) │ │ Coordinator) │ │ │ │ │
|
|
└──────────────────┘ └──────────────────┘ └────────────────────────┘ └────────────────────┘ └──────────────────┘
|
|
│ │ │ │ │
|
|
▼ ▼ ▼ ▼ ▼
|
|
Grades Entry Approve Quality Check Sign-off & Lock Print & Archive
|
|
(Oral/Written) Grades & Review
|
|
```
|
|
|
|
### Workflow States
|
|
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ DRAFT │────▶│ SUBMITTED │────▶│ REVIEWED │────▶│ SIGNED │────▶│ PRINTED │
|
|
│ (Entwurf) │ │ (Eingereicht)│ │ (Geprueft) │ │(Unterzeichnet) │ (Gedruckt) │
|
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
│ │ │ │
|
|
▼ ▼ ▼ ▼
|
|
Fachlehrer Klassenlehrer Zeugnisbeauftragter Schulleitung
|
|
```
|
|
|
|
## RBAC Integration
|
|
|
|
### Certificate-Related Roles
|
|
|
|
| Role | German | Description |
|
|
|------|--------|-------------|
|
|
| `FACHLEHRER` | Fachlehrer | Subject teacher - enters grades |
|
|
| `KLASSENLEHRER` | Klassenlehrer | Class teacher - approves class grades |
|
|
| `ZEUGNISBEAUFTRAGTER` | Zeugnisbeauftragter | Certificate coordinator - quality control |
|
|
| `SCHULLEITUNG` | Schulleitung | Principal - final sign-off |
|
|
| `SEKRETARIAT` | Sekretariat | Secretary - printing & archiving |
|
|
|
|
### Certificate Resource Types
|
|
|
|
| ResourceType | Description |
|
|
|--------------|-------------|
|
|
| `ZEUGNIS` | Final certificate document |
|
|
| `ZEUGNIS_VORLAGE` | Certificate template (per Bundesland) |
|
|
| `ZEUGNIS_ENTWURF` | Draft certificate (before approval) |
|
|
| `FACHNOTE` | Subject grade |
|
|
| `KOPFNOTE` | Head grade (Arbeits-/Sozialverhalten) |
|
|
| `BEMERKUNG` | Certificate remarks |
|
|
| `STATISTIK` | Class/subject statistics |
|
|
| `NOTENSPIEGEL` | Grade distribution chart |
|
|
|
|
### Permission Matrix
|
|
|
|
| Role | ZEUGNIS | ZEUGNIS_ENTWURF | ZEUGNIS_VORLAGE | FACHNOTE | Actions |
|
|
|------|---------|-----------------|-----------------|----------|---------|
|
|
| FACHLEHRER | R | CRUD | R | CRUD | Create/Update grades |
|
|
| KLASSENLEHRER | CRU | CRUD | R | CRUD | Approve class grades |
|
|
| ZEUGNISBEAUFTRAGTER | RU | RU | RUU | RU | Quality review |
|
|
| SCHULLEITUNG | R/SIGN/LOCK | RU | RU | R | Final approval |
|
|
| SEKRETARIAT | RD | R | R | R | Print & archive |
|
|
|
|
Legend: C=Create, R=Read, U=Update, D=Delete, SIGN=Sign-off, LOCK=Lock final
|
|
|
|
### VerfahrenType for Certificates
|
|
|
|
```python
|
|
class VerfahrenType(str, Enum):
|
|
# Exam types
|
|
ABITUR = "abitur"
|
|
KLAUSUR = "klausur"
|
|
...
|
|
|
|
# Certificate types
|
|
HALBJAHRESZEUGNIS = "halbjahreszeugnis" # Mid-year certificate
|
|
JAHRESZEUGNIS = "jahreszeugnis" # End-of-year certificate
|
|
ABSCHLUSSZEUGNIS = "abschlusszeugnis" # Graduation certificate
|
|
ABGANGSZEUGNIS = "abgangszeugnis" # Leaving certificate
|
|
```
|
|
|
|
## Statistics API
|
|
|
|
### Endpoints
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/school/statistics/:classId` | Class statistics |
|
|
| GET | `/api/v1/school/statistics/:classId/subject/:subjectId` | Subject statistics |
|
|
| GET | `/api/v1/school/statistics/student/:studentId` | Student statistics |
|
|
| GET | `/api/v1/school/statistics/:classId/notenspiegel` | Grade distribution |
|
|
|
|
### Response Structures
|
|
|
|
**ClassStatistics:**
|
|
```json
|
|
{
|
|
"class_id": "uuid",
|
|
"class_name": "5a",
|
|
"semester": 1,
|
|
"average": 2.4,
|
|
"pass_rate": 92.8,
|
|
"at_risk_count": 2,
|
|
"student_count": 25,
|
|
"subjects": [
|
|
{
|
|
"subject_id": "uuid",
|
|
"subject_name": "Mathematik",
|
|
"average": 2.8
|
|
}
|
|
],
|
|
"grade_distribution": {
|
|
"1": 3,
|
|
"2": 8,
|
|
"3": 10,
|
|
"4": 5,
|
|
"5": 2,
|
|
"6": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
**Notenspiegel:**
|
|
```json
|
|
{
|
|
"class_id": "uuid",
|
|
"subject_id": "uuid",
|
|
"exam_id": "uuid",
|
|
"distribution": {
|
|
"1": 2,
|
|
"2": 5,
|
|
"3": 8,
|
|
"4": 6,
|
|
"5": 3,
|
|
"6": 1
|
|
},
|
|
"total_students": 25,
|
|
"average": 3.1,
|
|
"median": 3.0
|
|
}
|
|
```
|
|
|
|
## Frontend Components
|
|
|
|
### Certificate Panel (`panel-school-certificates`)
|
|
|
|
Located in: `backend/frontend/modules/school.py`
|
|
|
|
Features:
|
|
- **Statistik-Karten**: Overview cards showing class average, pass rate, at-risk students
|
|
- **Notenspiegel Chart**: Bar chart visualization of grade distribution (1-6)
|
|
- **Workflow-Status**: Visual display of certificate approval chain
|
|
- **Student Table**: List of students with grades, attendance, certificate status
|
|
|
|
### Zeugnis-Wizard (5 Steps)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ Zeugnis-Wizard Modal │
|
|
├─────────────────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Step 1: Klasse auswaehlen │
|
|
│ ├── Dropdown: Klasse (5a, 5b, 6a, ...) │
|
|
│ ├── Dropdown: Halbjahr (1 oder 2) │
|
|
│ └── Vorschau: Anzahl Schueler, Durchschnitt │
|
|
│ │
|
|
│ Step 2: Noten pruefen │
|
|
│ ├── Tabelle: Schueler | Fach1 | Fach2 | ... | Status │
|
|
│ ├── Fehlende Noten markiert │
|
|
│ └── Edit-Moeglichkeit direkt in Tabelle │
|
|
│ │
|
|
│ Step 3: Vorlage waehlen │
|
|
│ ├── Dropdown: Bundesland (Niedersachsen, Bayern, ...) │
|
|
│ ├── Dropdown: Schulform (Gymnasium, Realschule, ...) │
|
|
│ └── Vorschau: Template-Preview │
|
|
│ │
|
|
│ Step 4: Bemerkungen │
|
|
│ ├── Textarea pro Schueler │
|
|
│ ├── Textbausteine / Vorlagen │
|
|
│ └── KI-generierte Vorschlaege (optional) │
|
|
│ │
|
|
│ Step 5: Zusammenfassung & Generieren │
|
|
│ ├── Uebersicht aller Einstellungen │
|
|
│ ├── Checkbox: Alle Zeugnisse generieren │
|
|
│ └── Button: Zeugnisse erstellen (mit Fortschrittsbalken) │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Seed Data Generator
|
|
|
|
Located in: `school-service/internal/seed/`
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Run seed data generation
|
|
go run cmd/seed/main.go -teacher-id=<teacher-uuid>
|
|
|
|
# Or with default teacher ID
|
|
go run cmd/seed/main.go
|
|
```
|
|
|
|
### Generated Data
|
|
|
|
| Entity | Count | Details |
|
|
|--------|-------|---------|
|
|
| School Years | 3 | 2022/23, 2023/24, 2024/25 |
|
|
| Classes per Year | 6 | 5a, 5b, 6a, 6b, 7a, 7b |
|
|
| Students per Class | 15-25 | Realistic German names |
|
|
| Subjects | 10 | Deutsch, Mathe, Englisch, ... |
|
|
| Exams per Class/Subject | 3-5 | With grade distribution |
|
|
| Attendance Records | Variable | 0-10 absence days |
|
|
|
|
### German Name Generator
|
|
|
|
```go
|
|
var firstNames = []string{
|
|
"Anna", "Emma", "Mia", "Sophie", "Marie", "Lena", "Lea", "Emily",
|
|
"Ben", "Paul", "Leon", "Luis", "Max", "Felix", "Noah", "Elias", ...
|
|
}
|
|
|
|
var lastNames = []string{
|
|
"Mueller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer",
|
|
"Wagner", "Becker", "Schulz", "Hoffmann", "Koch", "Richter", ...
|
|
}
|
|
```
|
|
|
|
## File Structure
|
|
|
|
```
|
|
school-service/
|
|
├── cmd/
|
|
│ ├── server/
|
|
│ │ └── main.go # Main server with all routes
|
|
│ └── seed/
|
|
│ └── main.go # Seed data CLI
|
|
├── internal/
|
|
│ ├── config/
|
|
│ │ └── config.go
|
|
│ ├── database/
|
|
│ │ └── database.go
|
|
│ ├── handlers/
|
|
│ │ ├── handlers.go # Base handler
|
|
│ │ ├── grade_handlers.go # Grade + Statistics endpoints
|
|
│ │ └── certificate_handlers.go
|
|
│ ├── services/
|
|
│ │ └── grade_service.go # Statistics calculations
|
|
│ ├── models/
|
|
│ │ └── models.go
|
|
│ └── seed/
|
|
│ └── seed_data.go # Fake data generator
|
|
└── go.mod
|
|
|
|
backend/frontend/modules/
|
|
└── school.py # Zeugnis-UI (panel-school-certificates)
|
|
|
|
klausur-service/backend/
|
|
├── rbac.py # RBAC with certificate roles
|
|
└── tests/
|
|
└── test_rbac.py # RBAC unit tests
|
|
```
|
|
|
|
## API Routes (School-Service)
|
|
|
|
### Grade Management
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/school/grades/:classId` | Get class grades |
|
|
| GET | `/api/v1/school/grades/student/:studentId` | Get student grades |
|
|
| PUT | `/api/v1/school/grades/:studentId/:subjectId/oral` | Update oral grade |
|
|
| POST | `/api/v1/school/grades/calculate` | Calculate final grades |
|
|
| POST | `/api/v1/school/grades/transfer` | Transfer approved grades |
|
|
| PUT | `/api/v1/school/grades/:studentId/:subjectId/lock` | Lock final grade |
|
|
| PUT | `/api/v1/school/grades/:studentId/:subjectId/weights` | Update grade weights |
|
|
|
|
### Statistics
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/school/statistics/:classId` | Class statistics |
|
|
| GET | `/api/v1/school/statistics/:classId/subject/:subjectId` | Subject statistics |
|
|
| GET | `/api/v1/school/statistics/student/:studentId` | Student statistics |
|
|
| GET | `/api/v1/school/statistics/:classId/notenspiegel` | Grade distribution |
|
|
|
|
### Certificates
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/v1/school/certificates/templates` | List templates |
|
|
| GET | `/api/v1/school/certificates/class/:classId` | Class certificates |
|
|
| POST | `/api/v1/school/certificates/generate` | Generate single |
|
|
| POST | `/api/v1/school/certificates/generate-bulk` | Generate bulk |
|
|
| GET | `/api/v1/school/certificates/detail/:id` | Get certificate |
|
|
| PUT | `/api/v1/school/certificates/detail/:id` | Update certificate |
|
|
| PUT | `/api/v1/school/certificates/detail/:id/finalize` | Finalize |
|
|
| GET | `/api/v1/school/certificates/detail/:id/pdf` | Download PDF |
|
|
| DELETE | `/api/v1/school/certificates/detail/:id` | Delete |
|
|
| GET | `/api/v1/school/certificates/feedback/:studentId` | AI feedback |
|
|
|
|
## German Grading System
|
|
|
|
| Grade | Meaning | Points |
|
|
|-------|---------|--------|
|
|
| 1 | sehr gut (excellent) | 15-13 |
|
|
| 2 | gut (good) | 12-10 |
|
|
| 3 | befriedigend (satisfactory) | 9-7 |
|
|
| 4 | ausreichend (adequate) | 6-4 |
|
|
| 5 | mangelhaft (poor) | 3-1 |
|
|
| 6 | ungenuegend (inadequate) | 0 |
|
|
|
|
### Grade Calculation
|
|
|
|
```
|
|
Final Grade = (Written Weight * Written Avg) + (Oral Weight * Oral Avg)
|
|
|
|
Default weights:
|
|
- Written (Klassenarbeiten): 50%
|
|
- Oral (muendliche Note): 50%
|
|
|
|
Customizable per subject/student via UpdateGradeWeights endpoint.
|
|
```
|
|
|
|
## Integration with BYOEH
|
|
|
|
The Zeugnis system can optionally integrate with BYOEH for:
|
|
- AI-generated certificate remarks
|
|
- Template suggestion based on student performance
|
|
- Feedback text generation (`/certificates/feedback/:studentId`)
|
|
|
|
## Security Considerations
|
|
|
|
1. **RBAC Enforcement**: All certificate operations check user role permissions
|
|
2. **Tenant Isolation**: Teachers only see their own classes/students
|
|
3. **Audit Trail**: All grade changes and approvals logged
|
|
4. **Lock Mechanism**: Finalized certificates cannot be modified
|
|
5. **Workflow Enforcement**: Cannot skip approval steps
|
|
|
|
## Future Enhancements
|
|
|
|
- [ ] PDF template editor (LaTeX/HTML)
|
|
- [ ] Bundesland-specific templates (all 16 states)
|
|
- [ ] Kopfnoten (head grades) support
|
|
- [ ] Digital signatures for certificates
|
|
- [ ] Parent portal access to certificates
|
|
- [ ] Archive/retention policies
|