[split-required] Split final 43 files (500-668 LOC) to complete refactoring
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>
This commit is contained in:
116
backend-lehrer/alerts_agent/api/digests_models.py
Normal file
116
backend-lehrer/alerts_agent/api/digests_models.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
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
|
||||
)
|
||||
Reference in New Issue
Block a user