mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
122 lines
3.8 KiB
Python
122 lines
3.8 KiB
Python
"""
|
||
Schema Pydantic per TenantSettings – lettura e aggiornamento impostazioni tenant.
|
||
Include schemi per il modulo di indicizzazione full-text.
|
||
"""
|
||
|
||
import uuid
|
||
from datetime import datetime
|
||
from typing import Literal, Optional
|
||
|
||
from pydantic import BaseModel, Field, field_validator
|
||
|
||
|
||
ArchivalMode = Literal["mock", "production"]
|
||
|
||
|
||
class TenantSettingsResponse(BaseModel):
|
||
"""
|
||
Risposta GET /settings.
|
||
|
||
Le credenziali del conservatore non vengono mai esposte in chiaro:
|
||
vengono restituite come flag booleani (is_configured).
|
||
"""
|
||
|
||
id: uuid.UUID
|
||
tenant_id: uuid.UUID
|
||
|
||
# Archiviazione
|
||
archival_mode: ArchivalMode
|
||
conservatore_id: str
|
||
conservatore_endpoint: str | None
|
||
conservatore_username_configured: bool # TRUE se la username è già salvata
|
||
conservatore_password_configured: bool # TRUE se la password è già salvata
|
||
archival_notes: str | None
|
||
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
class TenantSettingsUpdate(BaseModel):
|
||
"""
|
||
Body PUT /settings.
|
||
|
||
Tutti i campi sono opzionali (PATCH semantics).
|
||
Le credenziali vengono aggiornate solo se fornite.
|
||
Un valore esplicitamente None può essere usato per cancellare le credenziali.
|
||
"""
|
||
|
||
archival_mode: ArchivalMode | None = None
|
||
|
||
conservatore_id: str | None = Field(
|
||
default=None, min_length=1, max_length=100
|
||
)
|
||
|
||
# URL endpoint del conservatore (obbligatorio in produzione, ignorato in mock)
|
||
conservatore_endpoint: str | None = None
|
||
|
||
# Credenziali in chiaro: vengono cifrate prima del salvataggio.
|
||
# Valore stringa vuota ("") = cancella la credenziale.
|
||
conservatore_username: str | None = None
|
||
conservatore_password: str | None = None
|
||
|
||
archival_notes: str | None = None
|
||
|
||
@field_validator("archival_mode")
|
||
@classmethod
|
||
def validate_archival_mode(cls, v: str | None) -> str | None:
|
||
if v is not None and v not in ("mock", "production"):
|
||
raise ValueError("archival_mode deve essere 'mock' o 'production'")
|
||
return v
|
||
|
||
|
||
# ─── Schemi indicizzazione full-text ──────────────────────────────────────────
|
||
|
||
class IndexingStats(BaseModel):
|
||
"""Statistiche di copertura dell'indicizzazione per un tenant."""
|
||
|
||
total_messages: int
|
||
indexed_messages: int
|
||
unindexed_messages: int
|
||
coverage_pct: float # percentuale messaggi con search_vector != NULL
|
||
|
||
attachments_total: int # allegati PDF/DOCX totali
|
||
attachments_extracted: int # allegati con testo estratto
|
||
attachments_pct: float # percentuale allegati con testo estratto
|
||
|
||
|
||
class IndexingJobStatus(BaseModel):
|
||
"""Stato di un job di reindex in corso o completato."""
|
||
|
||
status: str # idle | running | completed | failed | cancelled
|
||
mode: Optional[str] = None # full | differential
|
||
total: int = 0
|
||
processed: int = 0
|
||
progress_pct: float = 0.0
|
||
|
||
started_at: Optional[str] = None # ISO datetime
|
||
finished_at: Optional[str] = None # ISO datetime
|
||
started_by: Optional[str] = None # email utente che ha avviato il job
|
||
elapsed_seconds: Optional[int] = None
|
||
is_stale: bool = False # True se running da piu' di STALE_THRESHOLD_HOURS
|
||
error: Optional[str] = None
|
||
|
||
|
||
class StartReindexRequest(BaseModel):
|
||
"""Body per POST /settings/indexing/reindex."""
|
||
|
||
mode: Literal["full", "differential"] = "differential"
|
||
|
||
|
||
class StartRescanRequest(BaseModel):
|
||
"""Body per POST /settings/indexing/rescan."""
|
||
|
||
force: bool = Field(
|
||
default=False,
|
||
description=(
|
||
"False (default): estrae solo allegati con extracted_text NULL. "
|
||
"True: ri-estrae tutti gli allegati, sovrascrivendo i testi gia' presenti."
|
||
),
|
||
)
|