Fascicoli+Tassonomia+permessi
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Schemi Pydantic per Fascicolo (fascicolazione pratiche).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ─── Schemi base ──────────────────────────────────────────────────────────────
|
||||
|
||||
class FascicoloCreate(BaseModel):
|
||||
titolo: str = Field(..., min_length=1, max_length=255)
|
||||
numero_pratica: Optional[str] = Field(None, max_length=100)
|
||||
stato: Optional[str] = Field("aperto", pattern=r"^(aperto|chiuso|archiviato)$")
|
||||
categoria: Optional[str] = Field(None, max_length=100)
|
||||
responsabile_id: Optional[uuid.UUID] = None
|
||||
scadenza: Optional[datetime] = None
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
class FascicoloUpdate(BaseModel):
|
||||
titolo: Optional[str] = Field(None, min_length=1, max_length=255)
|
||||
numero_pratica: Optional[str] = Field(None, max_length=100)
|
||||
stato: Optional[str] = Field(None, pattern=r"^(aperto|chiuso|archiviato)$")
|
||||
categoria: Optional[str] = Field(None, max_length=100)
|
||||
responsabile_id: Optional[uuid.UUID] = None
|
||||
scadenza: Optional[datetime] = None
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
class FascicoloResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
titolo: str
|
||||
numero_pratica: Optional[str] = None
|
||||
stato: str
|
||||
categoria: Optional[str] = None
|
||||
responsabile_id: Optional[uuid.UUID] = None
|
||||
scadenza: Optional[datetime] = None
|
||||
note: Optional[str] = None
|
||||
created_by: Optional[uuid.UUID] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
message_count: int = 0
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ─── Messaggi nel fascicolo ───────────────────────────────────────────────────
|
||||
|
||||
class FascicoloMessageItem(BaseModel):
|
||||
"""Riepilogo di un messaggio nel fascicolo."""
|
||||
id: uuid.UUID
|
||||
subject: Optional[str] = None
|
||||
from_address: Optional[str] = None
|
||||
to_addresses: Optional[list[str]] = None
|
||||
direction: str
|
||||
pec_type: str
|
||||
state: str
|
||||
mailbox_id: uuid.UUID
|
||||
received_at: Optional[datetime] = None
|
||||
sent_at: Optional[datetime] = None
|
||||
created_at: datetime
|
||||
added_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ─── Operazioni sui messaggi del fascicolo ────────────────────────────────────
|
||||
|
||||
class FascicoloAddMessagesRequest(BaseModel):
|
||||
message_ids: list[uuid.UUID] = Field(..., min_length=1)
|
||||
|
||||
|
||||
class FascicoloRemoveMessagesRequest(BaseModel):
|
||||
message_ids: list[uuid.UUID] = Field(..., min_length=1)
|
||||
|
||||
|
||||
# ─── Lista fascicoli di un messaggio ─────────────────────────────────────────
|
||||
|
||||
class MessageFascicoloSummary(BaseModel):
|
||||
"""Fascicolo sintetico per la vista nel dettaglio messaggio."""
|
||||
id: uuid.UUID
|
||||
titolo: str
|
||||
numero_pratica: Optional[str] = None
|
||||
stato: str
|
||||
categoria: Optional[str] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Schemi Pydantic per Label (tag) e operazioni correlate.
|
||||
Esteso con supporto tassonomia gerarchica (Feature N2).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
@@ -8,14 +9,21 @@ from typing import Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ─── CRUD Label ───────────────────────────────────────────────────────────────
|
||||
|
||||
class LabelCreate(BaseModel):
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
color: Optional[str] = Field(None, pattern=r'^#[0-9A-Fa-f]{6}$')
|
||||
# Tassonomia: se valorizzato, questo nodo diventa figlio del parent indicato
|
||||
parent_id: Optional[uuid.UUID] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class LabelUpdate(BaseModel):
|
||||
name: Optional[str] = Field(None, min_length=1, max_length=100)
|
||||
color: Optional[str] = Field(None, pattern=r'^#[0-9A-Fa-f]{6}$')
|
||||
parent_id: Optional[uuid.UUID] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class LabelResponse(BaseModel):
|
||||
@@ -23,10 +31,34 @@ class LabelResponse(BaseModel):
|
||||
tenant_id: uuid.UUID
|
||||
name: str
|
||||
color: Optional[str] = None
|
||||
parent_id: Optional[uuid.UUID] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class LabelTreeResponse(BaseModel):
|
||||
"""
|
||||
Label con figli annidati per la vista ad albero della tassonomia.
|
||||
|
||||
Struttura restituita da GET /labels/tree:
|
||||
[ Ambito1 { children: [ Processo1 { children: [ Classificazione1, ... ] } ] } ]
|
||||
"""
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
name: str
|
||||
color: Optional[str] = None
|
||||
parent_id: Optional[uuid.UUID] = None
|
||||
description: Optional[str] = None
|
||||
children: list["LabelTreeResponse"] = []
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# Necessario per il tipo ricorsivo
|
||||
LabelTreeResponse.model_rebuild()
|
||||
|
||||
|
||||
# ─── Richieste per assegnazione tag a messaggi ────────────────────────────────
|
||||
|
||||
class MessageLabelSetRequest(BaseModel):
|
||||
|
||||
@@ -76,6 +76,9 @@ class MessageResponse(BaseModel):
|
||||
pending_conservation_at: Optional[datetime] = None
|
||||
is_conserved: bool = False
|
||||
conserved_at: Optional[datetime] = None
|
||||
# Rischio e Riservatezza (Feature N3)
|
||||
risk_level: Optional[str] = None
|
||||
confidentiality: Optional[str] = None
|
||||
raw_eml_path: Optional[str] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
@@ -116,6 +119,9 @@ class MessageUpdateRequest(BaseModel):
|
||||
is_trashed: Optional[bool] = None
|
||||
is_pending_conservation: Optional[bool] = None
|
||||
is_conserved: Optional[bool] = None
|
||||
# Rischio e Riservatezza (Feature N3) — None = non modificare; stringa vuota = reset a NULL
|
||||
risk_level: Optional[str] = None
|
||||
confidentiality: Optional[str] = None
|
||||
|
||||
|
||||
class MessageBulkUpdateRequest(BaseModel):
|
||||
@@ -126,6 +132,8 @@ class MessageBulkUpdateRequest(BaseModel):
|
||||
is_trashed: Optional[bool] = None
|
||||
is_pending_conservation: Optional[bool] = None
|
||||
is_conserved: Optional[bool] = None
|
||||
risk_level: Optional[str] = None
|
||||
confidentiality: Optional[str] = None
|
||||
|
||||
|
||||
class MessageBulkUpdateResponse(BaseModel):
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
Schema Pydantic per i preset di permessi (sottoruoli nominati).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PermissionPresetCreate(BaseModel):
|
||||
name: str = Field(..., min_length=1, max_length=100, description="Nome del preset")
|
||||
description: str | None = Field(None, description="Descrizione opzionale")
|
||||
can_read: bool = Field(True, description="Permesso lettura messaggi")
|
||||
can_send: bool = Field(False, description="Permesso invio PEC")
|
||||
can_manage: bool = Field(False, description="Permesso gestione casella")
|
||||
can_conserve: bool = Field(False, description="Permesso conservazione documenti")
|
||||
|
||||
|
||||
class PermissionPresetUpdate(BaseModel):
|
||||
name: str | None = Field(None, min_length=1, max_length=100)
|
||||
description: str | None = None
|
||||
can_read: bool | None = None
|
||||
can_send: bool | None = None
|
||||
can_manage: bool | None = None
|
||||
can_conserve: bool | None = None
|
||||
|
||||
|
||||
class PermissionPresetResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
name: str
|
||||
description: str | None
|
||||
can_read: bool
|
||||
can_send: bool
|
||||
can_manage: bool
|
||||
can_conserve: bool
|
||||
created_by: uuid.UUID | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
@@ -10,7 +10,16 @@ from pydantic import BaseModel, field_validator
|
||||
|
||||
# Valori validi per field nelle condizioni
|
||||
CONDITION_FIELDS = Literal[
|
||||
"from_address", "to_address", "subject", "mailbox_id", "pec_type"
|
||||
"from_address",
|
||||
"to_address",
|
||||
"subject",
|
||||
"mailbox_id",
|
||||
"pec_type",
|
||||
# Tassonomia (N2): verifica se il messaggio ha gia' una specifica etichetta/nodo
|
||||
"has_label",
|
||||
# Rischio e Riservatezza (N3): verifica il livello gia' impostato
|
||||
"risk_level",
|
||||
"confidentiality",
|
||||
]
|
||||
# Operatori supportati
|
||||
CONDITION_OPERATORS = Literal[
|
||||
@@ -18,7 +27,16 @@ CONDITION_OPERATORS = Literal[
|
||||
]
|
||||
# Tipi di azione
|
||||
ACTION_TYPES = Literal[
|
||||
"apply_label", "assign_vbox", "mark_read", "mark_starred", "notify_webhook"
|
||||
"apply_label",
|
||||
"assign_vbox",
|
||||
"mark_read",
|
||||
"mark_starred",
|
||||
"notify_webhook",
|
||||
# Tassonomia (N2): applica un nodo tassonomico (Ambito/Processo/Classificazione)
|
||||
"apply_taxonomy",
|
||||
# Rischio e Riservatezza (N3): imposta il livello di rischio o riservatezza
|
||||
"set_risk_level",
|
||||
"set_confidentiality",
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user