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>
201 lines
5.7 KiB
Python
201 lines
5.7 KiB
Python
"""
|
|
Schools API - Pydantic Models.
|
|
|
|
Data models for school and school staff endpoints.
|
|
"""
|
|
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# =============================================================================
|
|
# School Type Models
|
|
# =============================================================================
|
|
|
|
|
|
class SchoolTypeResponse(BaseModel):
|
|
"""School type response model."""
|
|
id: str
|
|
name: str
|
|
name_short: Optional[str] = None
|
|
category: Optional[str] = None
|
|
description: Optional[str] = None
|
|
|
|
|
|
# =============================================================================
|
|
# School Models
|
|
# =============================================================================
|
|
|
|
|
|
class SchoolBase(BaseModel):
|
|
"""Base school model for creation/update."""
|
|
name: str = Field(..., max_length=255)
|
|
school_number: Optional[str] = Field(None, max_length=20)
|
|
school_type_id: Optional[str] = None
|
|
school_type_raw: Optional[str] = None
|
|
state: str = Field(..., max_length=10)
|
|
district: Optional[str] = None
|
|
city: Optional[str] = None
|
|
postal_code: Optional[str] = None
|
|
street: Optional[str] = None
|
|
address_full: Optional[str] = None
|
|
latitude: Optional[float] = None
|
|
longitude: Optional[float] = None
|
|
website: Optional[str] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
fax: Optional[str] = None
|
|
principal_name: Optional[str] = None
|
|
principal_title: Optional[str] = None
|
|
principal_email: Optional[str] = None
|
|
principal_phone: Optional[str] = None
|
|
secretary_name: Optional[str] = None
|
|
secretary_email: Optional[str] = None
|
|
secretary_phone: Optional[str] = None
|
|
student_count: Optional[int] = None
|
|
teacher_count: Optional[int] = None
|
|
class_count: Optional[int] = None
|
|
founded_year: Optional[int] = None
|
|
is_public: bool = True
|
|
is_all_day: Optional[bool] = None
|
|
has_inclusion: Optional[bool] = None
|
|
languages: Optional[List[str]] = None
|
|
specializations: Optional[List[str]] = None
|
|
source: Optional[str] = None
|
|
source_url: Optional[str] = None
|
|
|
|
|
|
class SchoolCreate(SchoolBase):
|
|
"""School creation model."""
|
|
pass
|
|
|
|
|
|
class SchoolUpdate(BaseModel):
|
|
"""School update model (all fields optional)."""
|
|
name: Optional[str] = Field(None, max_length=255)
|
|
school_number: Optional[str] = None
|
|
school_type_id: Optional[str] = None
|
|
state: Optional[str] = None
|
|
district: Optional[str] = None
|
|
city: Optional[str] = None
|
|
postal_code: Optional[str] = None
|
|
street: Optional[str] = None
|
|
website: Optional[str] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
principal_name: Optional[str] = None
|
|
student_count: Optional[int] = None
|
|
teacher_count: Optional[int] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
|
|
class SchoolResponse(BaseModel):
|
|
"""School response model."""
|
|
id: str
|
|
name: str
|
|
school_number: Optional[str] = None
|
|
school_type: Optional[str] = None
|
|
school_type_short: Optional[str] = None
|
|
school_category: Optional[str] = None
|
|
state: str
|
|
district: Optional[str] = None
|
|
city: Optional[str] = None
|
|
postal_code: Optional[str] = None
|
|
street: Optional[str] = None
|
|
address_full: Optional[str] = None
|
|
latitude: Optional[float] = None
|
|
longitude: Optional[float] = None
|
|
website: Optional[str] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
fax: Optional[str] = None
|
|
principal_name: Optional[str] = None
|
|
principal_email: Optional[str] = None
|
|
student_count: Optional[int] = None
|
|
teacher_count: Optional[int] = None
|
|
is_public: bool = True
|
|
is_all_day: Optional[bool] = None
|
|
staff_count: int = 0
|
|
source: Optional[str] = None
|
|
crawled_at: Optional[datetime] = None
|
|
is_active: bool = True
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class SchoolsListResponse(BaseModel):
|
|
"""List response with pagination info."""
|
|
schools: List[SchoolResponse]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class SchoolStatsResponse(BaseModel):
|
|
"""School statistics response."""
|
|
total_schools: int
|
|
total_staff: int
|
|
schools_by_state: dict
|
|
schools_by_type: dict
|
|
schools_with_website: int
|
|
schools_with_email: int
|
|
schools_with_principal: int
|
|
total_students: int
|
|
total_teachers: int
|
|
last_crawl_time: Optional[datetime] = None
|
|
|
|
|
|
class BulkImportRequest(BaseModel):
|
|
"""Bulk import request."""
|
|
schools: List[SchoolCreate]
|
|
|
|
|
|
class BulkImportResponse(BaseModel):
|
|
"""Bulk import response."""
|
|
imported: int
|
|
updated: int
|
|
skipped: int
|
|
errors: List[str]
|
|
|
|
|
|
# =============================================================================
|
|
# School Staff Models
|
|
# =============================================================================
|
|
|
|
|
|
class SchoolStaffBase(BaseModel):
|
|
"""Base school staff model."""
|
|
first_name: Optional[str] = None
|
|
last_name: str
|
|
full_name: Optional[str] = None
|
|
title: Optional[str] = None
|
|
position: Optional[str] = None
|
|
position_type: Optional[str] = None
|
|
subjects: Optional[List[str]] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
|
|
|
|
class SchoolStaffCreate(SchoolStaffBase):
|
|
"""School staff creation model."""
|
|
school_id: str
|
|
|
|
|
|
class SchoolStaffResponse(SchoolStaffBase):
|
|
"""School staff response model."""
|
|
id: str
|
|
school_id: str
|
|
school_name: Optional[str] = None
|
|
profile_url: Optional[str] = None
|
|
photo_url: Optional[str] = None
|
|
is_active: bool = True
|
|
created_at: datetime
|
|
|
|
|
|
class SchoolStaffListResponse(BaseModel):
|
|
"""Staff list response."""
|
|
staff: List[SchoolStaffResponse]
|
|
total: int
|