klausur-service (11 files): - cv_gutter_repair, ocr_pipeline_regression, upload_api - ocr_pipeline_sessions, smart_spell, nru_worksheet_generator - ocr_pipeline_overlays, mail/aggregator, zeugnis_api - cv_syllable_detect, self_rag backend-lehrer (17 files): - classroom_engine/suggestions, generators/quiz_generator - worksheets_api, llm_gateway/comparison, state_engine_api - classroom/models (→ 4 submodules), services/file_processor - alerts_agent/api/wizard+digests+routes, content_generators/pdf - classroom/routes/sessions, llm_gateway/inference - classroom_engine/analytics, auth/keycloak_auth - alerts_agent/processing/rule_engine, ai_processor/print_versions agent-core (5 files): - brain/memory_store, brain/knowledge_graph, brain/context_manager - orchestrator/supervisor, sessions/session_manager admin-lehrer (5 components): - GridOverlay, StepGridReview, DevOpsPipelineSidebar - DataFlowDiagram, sbom/wizard/page website (2 files): - DependencyMap, lehrer/abitur-archiv Other: nibis_ingestion, grid_detection_service, export-doclayout-onnx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
117 lines
3.4 KiB
Python
117 lines
3.4 KiB
Python
"""
|
|
Alert Digests - Request/Response Models und Konverter.
|
|
"""
|
|
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
from pydantic import BaseModel, Field
|
|
|
|
from ..db.models import AlertDigestDB
|
|
|
|
|
|
# ============================================================================
|
|
# Request/Response Models
|
|
# ============================================================================
|
|
|
|
class DigestListItem(BaseModel):
|
|
"""Kurze Digest-Info fuer Liste."""
|
|
id: str
|
|
period_start: datetime
|
|
period_end: datetime
|
|
total_alerts: int
|
|
critical_count: int
|
|
urgent_count: int
|
|
status: str
|
|
created_at: datetime
|
|
|
|
|
|
class DigestDetail(BaseModel):
|
|
"""Vollstaendige Digest-Details."""
|
|
id: str
|
|
subscription_id: Optional[str]
|
|
user_id: str
|
|
period_start: datetime
|
|
period_end: datetime
|
|
summary_html: str
|
|
summary_pdf_url: Optional[str]
|
|
total_alerts: int
|
|
critical_count: int
|
|
urgent_count: int
|
|
important_count: int
|
|
review_count: int
|
|
info_count: int
|
|
status: str
|
|
sent_at: Optional[datetime]
|
|
created_at: datetime
|
|
|
|
|
|
class DigestListResponse(BaseModel):
|
|
"""Response fuer Digest-Liste."""
|
|
digests: List[DigestListItem]
|
|
total: int
|
|
|
|
|
|
class GenerateDigestRequest(BaseModel):
|
|
"""Request fuer manuelle Digest-Generierung."""
|
|
weeks_back: int = Field(default=1, ge=1, le=4, description="Wochen zurueck")
|
|
force_regenerate: bool = Field(default=False, description="Vorhandenen Digest ueberschreiben")
|
|
|
|
|
|
class GenerateDigestResponse(BaseModel):
|
|
"""Response fuer Digest-Generierung."""
|
|
status: str
|
|
digest_id: Optional[str]
|
|
message: str
|
|
|
|
|
|
class SendEmailRequest(BaseModel):
|
|
"""Request fuer E-Mail-Versand."""
|
|
email: Optional[str] = Field(default=None, description="E-Mail-Adresse (optional)")
|
|
|
|
|
|
class SendEmailResponse(BaseModel):
|
|
"""Response fuer E-Mail-Versand."""
|
|
status: str
|
|
sent_to: str
|
|
message: str
|
|
|
|
|
|
# ============================================================================
|
|
# Converter Functions
|
|
# ============================================================================
|
|
|
|
def digest_to_list_item(digest: AlertDigestDB) -> DigestListItem:
|
|
"""Konvertiere DB-Model zu List-Item."""
|
|
return DigestListItem(
|
|
id=digest.id,
|
|
period_start=digest.period_start,
|
|
period_end=digest.period_end,
|
|
total_alerts=digest.total_alerts or 0,
|
|
critical_count=digest.critical_count or 0,
|
|
urgent_count=digest.urgent_count or 0,
|
|
status=digest.status.value if digest.status else "pending",
|
|
created_at=digest.created_at
|
|
)
|
|
|
|
|
|
def digest_to_detail(digest: AlertDigestDB) -> DigestDetail:
|
|
"""Konvertiere DB-Model zu Detail."""
|
|
return DigestDetail(
|
|
id=digest.id,
|
|
subscription_id=digest.subscription_id,
|
|
user_id=digest.user_id,
|
|
period_start=digest.period_start,
|
|
period_end=digest.period_end,
|
|
summary_html=digest.summary_html or "",
|
|
summary_pdf_url=digest.summary_pdf_url,
|
|
total_alerts=digest.total_alerts or 0,
|
|
critical_count=digest.critical_count or 0,
|
|
urgent_count=digest.urgent_count or 0,
|
|
important_count=digest.important_count or 0,
|
|
review_count=digest.review_count or 0,
|
|
info_count=digest.info_count or 0,
|
|
status=digest.status.value if digest.status else "pending",
|
|
sent_at=digest.sent_at,
|
|
created_at=digest.created_at
|
|
)
|