Fascicoli+Tassonomia+permessi

This commit is contained in:
2026-06-17 21:47:46 +02:00
parent e31676d22e
commit 3fd3c72f06
42 changed files with 4554 additions and 99 deletions
+21 -4
View File
@@ -1,10 +1,17 @@
"""
Modelli Label e MessageLabel tagging messaggi.
Modelli Label e MessageLabel tagging messaggi con supporto tassonomia gerarchica.
Struttura ad albero (Feature N2 Tassonomia di Classificazione Multi-livello):
parent_id = NULL → Livello 0: Ambito (Area Aziendale)
parent_id = ID ambito → Livello 1: Processo
parent_id = ID processo → Livello 2: Classificazione (foglia)
Le label senza parent_id sono label "piatte" classiche (comportamento pre-esistente).
"""
import uuid
from sqlalchemy import CHAR, ForeignKey, Index, String, UniqueConstraint
from sqlalchemy import CHAR, ForeignKey, Index, String, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column
@@ -20,15 +27,25 @@ class Label(Base):
tenant_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False
)
# Tassonomia: se parent_id è None è un nodo radice (Ambito) o label piatta
parent_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("labels.id", ondelete="CASCADE"),
nullable=True,
)
name: Mapped[str] = mapped_column(String(100), nullable=False)
color: Mapped[str | None] = mapped_column(CHAR(7), nullable=True) # hex #RRGGBB
description: Mapped[str | None] = mapped_column(Text, nullable=True)
# Nota: i vincoli di unicità sono gestiti da indici parziali nel DB:
# uq_label_name_root UNIQUE (tenant_id, name) WHERE parent_id IS NULL
# uq_label_name_parent UNIQUE (tenant_id, name, parent_id) WHERE parent_id IS NOT NULL
__table_args__ = (
UniqueConstraint("tenant_id", "name", name="uq_label_name_tenant"),
Index("idx_labels_parent", "parent_id"),
)
def __repr__(self) -> str:
return f"<Label {self.name!r}>"
return f"<Label {self.name!r} parent={self.parent_id}>"
class MessageLabel(Base):