mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
Implementazioni varie
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Schemi Pydantic per PecContact (Feature 6 – Rubrica indirizzi PEC).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, EmailStr, field_validator
|
||||
|
||||
|
||||
class PecContactCreate(BaseModel):
|
||||
email: EmailStr
|
||||
name: str | None = None
|
||||
organization: str | None = None
|
||||
notes: str | None = None
|
||||
is_favorite: bool = False
|
||||
|
||||
@field_validator("email")
|
||||
@classmethod
|
||||
def email_lowercase(cls, v: str) -> str:
|
||||
return v.lower().strip()
|
||||
|
||||
|
||||
class PecContactUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
organization: str | None = None
|
||||
notes: str | None = None
|
||||
is_favorite: bool | None = None
|
||||
|
||||
|
||||
class PecContactResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
email: str
|
||||
name: str | None = None
|
||||
organization: str | None = None
|
||||
notes: str | None = None
|
||||
is_favorite: bool
|
||||
auto_saved: bool
|
||||
created_by: uuid.UUID | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class PecContactListResponse(BaseModel):
|
||||
items: list[PecContactResponse]
|
||||
total: int
|
||||
|
||||
|
||||
class PecContactImportResult(BaseModel):
|
||||
created: int
|
||||
updated: int
|
||||
skipped: int
|
||||
errors: list[str] = []
|
||||
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
Schemi Pydantic per RoutingRule (Feature 2 – Regole di smistamento automatico).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
# Valori validi per field nelle condizioni
|
||||
CONDITION_FIELDS = Literal[
|
||||
"from_address", "to_address", "subject", "mailbox_id", "pec_type"
|
||||
]
|
||||
# Operatori supportati
|
||||
CONDITION_OPERATORS = Literal[
|
||||
"contains", "equals", "starts_with", "ends_with", "regex", "not_contains"
|
||||
]
|
||||
# Tipi di azione
|
||||
ACTION_TYPES = Literal[
|
||||
"apply_label", "assign_vbox", "mark_read", "mark_starred", "notify_webhook"
|
||||
]
|
||||
|
||||
|
||||
class RoutingRuleConditionCreate(BaseModel):
|
||||
field: CONDITION_FIELDS
|
||||
operator: CONDITION_OPERATORS = "contains"
|
||||
value: str
|
||||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def value_not_empty(cls, v: str) -> str:
|
||||
if not v.strip():
|
||||
raise ValueError("Il valore della condizione non puo' essere vuoto")
|
||||
return v.strip()
|
||||
|
||||
|
||||
class RoutingRuleActionCreate(BaseModel):
|
||||
action_type: ACTION_TYPES
|
||||
action_value: str | None = None
|
||||
|
||||
|
||||
class RoutingRuleCreate(BaseModel):
|
||||
name: str
|
||||
description: str | None = None
|
||||
is_active: bool = True
|
||||
priority: int = 100
|
||||
stop_processing: bool = True
|
||||
conditions: list[RoutingRuleConditionCreate] = []
|
||||
actions: list[RoutingRuleActionCreate] = []
|
||||
|
||||
@field_validator("name")
|
||||
@classmethod
|
||||
def name_not_empty(cls, v: str) -> str:
|
||||
if not v.strip():
|
||||
raise ValueError("Il nome della regola non puo' essere vuoto")
|
||||
return v.strip()
|
||||
|
||||
@field_validator("priority")
|
||||
@classmethod
|
||||
def priority_positive(cls, v: int) -> int:
|
||||
if v < 1:
|
||||
raise ValueError("La priorita' deve essere >= 1")
|
||||
return v
|
||||
|
||||
|
||||
class RoutingRuleUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
is_active: bool | None = None
|
||||
priority: int | None = None
|
||||
stop_processing: bool | None = None
|
||||
conditions: list[RoutingRuleConditionCreate] | None = None
|
||||
actions: list[RoutingRuleActionCreate] | None = None
|
||||
|
||||
|
||||
class RoutingRuleConditionResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
field: str
|
||||
operator: str
|
||||
value: str
|
||||
|
||||
|
||||
class RoutingRuleActionResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
action_type: str
|
||||
action_value: str | None = None
|
||||
|
||||
|
||||
class RoutingRuleResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
name: str
|
||||
description: str | None = None
|
||||
is_active: bool
|
||||
priority: int
|
||||
stop_processing: bool
|
||||
conditions: list[RoutingRuleConditionResponse] = []
|
||||
actions: list[RoutingRuleActionResponse] = []
|
||||
created_by: uuid.UUID | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class RoutingRuleListResponse(BaseModel):
|
||||
items: list[RoutingRuleResponse]
|
||||
total: int
|
||||
@@ -37,6 +37,9 @@ class SendPecRequest(BaseModel):
|
||||
reply_to_message_id: uuid.UUID | None = None
|
||||
"""UUID del messaggio a cui si risponde (per threading, opzionale)."""
|
||||
|
||||
scheduled_at: datetime | None = None
|
||||
"""Data/ora di invio differito (Feature 5). Se None, invio immediato."""
|
||||
|
||||
@field_validator("to_addresses")
|
||||
@classmethod
|
||||
def at_least_one_recipient(cls, v: list[EmailStr]) -> list[EmailStr]:
|
||||
@@ -67,6 +70,7 @@ class SendJobResponse(BaseModel):
|
||||
max_attempts: int
|
||||
next_retry_at: datetime | None = None
|
||||
last_error: str | None = None
|
||||
scheduled_at: datetime | None = None
|
||||
queued_at: datetime
|
||||
sent_at: datetime | None = None
|
||||
created_by: uuid.UUID | None = None
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Schemi Pydantic per MessageTemplate (Feature 1 – Template messaggi).
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
|
||||
class TemplateCreate(BaseModel):
|
||||
name: str
|
||||
description: str | None = None
|
||||
subject: str = ""
|
||||
body_text: str | None = None
|
||||
body_html: str | None = None
|
||||
|
||||
@field_validator("name")
|
||||
@classmethod
|
||||
def name_not_empty(cls, v: str) -> str:
|
||||
if not v.strip():
|
||||
raise ValueError("Il nome del template non puo' essere vuoto")
|
||||
return v.strip()
|
||||
|
||||
|
||||
class TemplateUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
subject: str | None = None
|
||||
body_text: str | None = None
|
||||
body_html: str | None = None
|
||||
|
||||
|
||||
class TemplateResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
id: uuid.UUID
|
||||
tenant_id: uuid.UUID
|
||||
name: str
|
||||
description: str | None = None
|
||||
subject: str
|
||||
body_text: str | None = None
|
||||
body_html: str | None = None
|
||||
created_by: uuid.UUID | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class TemplateListResponse(BaseModel):
|
||||
items: list[TemplateResponse]
|
||||
total: int
|
||||
Reference in New Issue
Block a user