backend-lehrer (11 files): - llm_gateway/routes/schools.py (867 → 5), recording_api.py (848 → 6) - messenger_api.py (840 → 5), print_generator.py (824 → 5) - unit_analytics_api.py (751 → 5), classroom/routes/context.py (726 → 4) - llm_gateway/routes/edu_search_seeds.py (710 → 4) klausur-service (12 files): - ocr_labeling_api.py (845 → 4), metrics_db.py (833 → 4) - legal_corpus_api.py (790 → 4), page_crop.py (758 → 3) - mail/ai_service.py (747 → 4), github_crawler.py (767 → 3) - trocr_service.py (730 → 4), full_compliance_pipeline.py (723 → 4) - dsfa_rag_api.py (715 → 4), ocr_pipeline_auto.py (705 → 4) website (6 pages): - audit-checklist (867 → 8), content (806 → 6) - screen-flow (790 → 4), scraper (789 → 5) - zeugnisse (776 → 5), modules (745 → 4) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
140 lines
3.8 KiB
Python
140 lines
3.8 KiB
Python
"""
|
|
Messenger API - Pydantic Models.
|
|
|
|
Data models for contacts, conversations, messages, and groups.
|
|
"""
|
|
|
|
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# ==========================================
|
|
# CONTACT MODELS
|
|
# ==========================================
|
|
|
|
class ContactBase(BaseModel):
|
|
"""Basis-Modell fuer Kontakte."""
|
|
name: str = Field(..., min_length=1, max_length=200)
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
role: str = Field(default="parent", description="parent, teacher, staff, student")
|
|
student_name: Optional[str] = Field(None, description="Name des zugehoerigen Schuelers")
|
|
class_name: Optional[str] = Field(None, description="Klasse z.B. 10a")
|
|
notes: Optional[str] = None
|
|
tags: List[str] = Field(default_factory=list)
|
|
matrix_id: Optional[str] = Field(None, description="Matrix-ID z.B. @user:matrix.org")
|
|
preferred_channel: str = Field(default="email", description="email, matrix, pwa")
|
|
|
|
|
|
class ContactCreate(ContactBase):
|
|
"""Model fuer neuen Kontakt."""
|
|
pass
|
|
|
|
|
|
class Contact(ContactBase):
|
|
"""Vollstaendiger Kontakt mit ID."""
|
|
id: str
|
|
created_at: str
|
|
updated_at: str
|
|
online: bool = False
|
|
last_seen: Optional[str] = None
|
|
|
|
|
|
class ContactUpdate(BaseModel):
|
|
"""Update-Model fuer Kontakte."""
|
|
name: Optional[str] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
role: Optional[str] = None
|
|
student_name: Optional[str] = None
|
|
class_name: Optional[str] = None
|
|
notes: Optional[str] = None
|
|
tags: Optional[List[str]] = None
|
|
matrix_id: Optional[str] = None
|
|
preferred_channel: Optional[str] = None
|
|
|
|
|
|
# ==========================================
|
|
# GROUP MODELS
|
|
# ==========================================
|
|
|
|
class GroupBase(BaseModel):
|
|
"""Basis-Modell fuer Gruppen."""
|
|
name: str = Field(..., min_length=1, max_length=100)
|
|
description: Optional[str] = None
|
|
group_type: str = Field(default="class", description="class, department, custom")
|
|
|
|
|
|
class GroupCreate(GroupBase):
|
|
"""Model fuer neue Gruppe."""
|
|
member_ids: List[str] = Field(default_factory=list)
|
|
|
|
|
|
class Group(GroupBase):
|
|
"""Vollstaendige Gruppe mit ID."""
|
|
id: str
|
|
member_ids: List[str] = []
|
|
created_at: str
|
|
updated_at: str
|
|
|
|
|
|
# ==========================================
|
|
# MESSAGE MODELS
|
|
# ==========================================
|
|
|
|
class MessageBase(BaseModel):
|
|
"""Basis-Modell fuer Nachrichten."""
|
|
content: str = Field(..., min_length=1)
|
|
content_type: str = Field(default="text", description="text, file, image")
|
|
file_url: Optional[str] = None
|
|
send_email: bool = Field(default=False, description="Nachricht auch per Email senden")
|
|
|
|
|
|
class MessageCreate(MessageBase):
|
|
"""Model fuer neue Nachricht."""
|
|
conversation_id: str
|
|
|
|
|
|
class Message(MessageBase):
|
|
"""Vollstaendige Nachricht mit ID."""
|
|
id: str
|
|
conversation_id: str
|
|
sender_id: str # "self" fuer eigene Nachrichten
|
|
timestamp: str
|
|
read: bool = False
|
|
read_at: Optional[str] = None
|
|
email_sent: bool = False
|
|
email_sent_at: Optional[str] = None
|
|
email_error: Optional[str] = None
|
|
|
|
|
|
# ==========================================
|
|
# CONVERSATION MODELS
|
|
# ==========================================
|
|
|
|
class ConversationBase(BaseModel):
|
|
"""Basis-Modell fuer Konversationen."""
|
|
name: Optional[str] = None
|
|
is_group: bool = False
|
|
|
|
|
|
class Conversation(ConversationBase):
|
|
"""Vollstaendige Konversation mit ID."""
|
|
id: str
|
|
participant_ids: List[str] = []
|
|
group_id: Optional[str] = None
|
|
created_at: str
|
|
updated_at: str
|
|
last_message: Optional[str] = None
|
|
last_message_time: Optional[str] = None
|
|
unread_count: int = 0
|
|
|
|
|
|
class CSVImportResult(BaseModel):
|
|
"""Ergebnis eines CSV-Imports."""
|
|
imported: int
|
|
skipped: int
|
|
errors: List[str]
|
|
contacts: List[Contact]
|