Tenant — Modèles

Les modèles du Tenant Context gèrent les organisations (tenants), les memberships utilisateur-tenant, les rôles, départements et invitations.

Module : src.module.tenant.infrastructure.models

Tenant

class src.module.tenant.infrastructure.models.Tenant(models.Model)

Agrégat racine représentant une organisation/tenant.

id: UUIDField

Clé primaire UUID4.

name: CharField(max_length=255)

Nom de l’organisation.

slug: SlugField(unique=True)

Identifiant URL-safe unique (ex: acme-corp).

schema_name: CharField(max_length=63, unique=True)

Nom du schéma PostgreSQL (auto-généré : tenant_<slug>).

status: CharField

Statut du tenant : active, suspended, archived. Utilise l’enum TenantStatus.

metadata: JSONField

Métadonnées libres (plan, config custom, etc.).

Méthodes de cycle de vie :

suspend() None

Passe le tenant en statut suspended. Émet TenantSuspended.

activate() None

Réactive un tenant suspendu. Émet TenantActivated.

archive() None

Archive définitivement un tenant. Émet TenantArchived.

tenant = Tenant.objects.create(
    name="Acme Corp",
    slug="acme-corp",
)
# schema_name = "tenant_acme_corp" (auto-généré)

TenantMembership

class src.module.tenant.infrastructure.models.TenantMembership(models.Model)

Pivot utilisateur-tenant avec rôles et attributs ABAC.

user: ForeignKey User
tenant: ForeignKey Tenant
roles: JSONField

Liste de rôles (ex: ["admin", "billing"]).

abac_attributes: JSONField

Attributs ABAC personnalisés (ex: {"department": "finance", "level": 3}).

department: ForeignKey Department (nullable)
status: CharField

Statut : active, invited, suspended.

Méthodes :

update_roles(new_roles: list[str]) None

Met à jour les rôles. Émet MemberRolesUpdated.

Role

class src.module.tenant.infrastructure.models.Role(TranslatableSharedModel)

Définitions de rôles par tenant pour le système ABAC. Traduisible via django-parler.

tenant: ForeignKey Tenant
name: CharField

Identifiant programmatique du rôle (non traduit, utilisé dans les conditions ABAC et les listes JSON de rôles).

display_name: CharField(traduit)

Nom d’affichage traduisible.

description: TextField(traduit)

Description traduisible du rôle.

is_active: BooleanField
Table:

mt_tenant_role / mt_tenant_role_translation

Department

class src.module.tenant.infrastructure.models.Department(TranslatableSharedModel)

Départements par tenant. Traduisible via django-parler.

tenant: ForeignKey Tenant
name: CharField

Identifiant programmatique (non traduit).

display_name: CharField(traduit)

Nom d’affichage traduisible.

description: TextField(traduit)

Description traduisible du département.

is_active: BooleanField
Table:

mt_department / mt_department_translation

Invitation

class src.module.tenant.infrastructure.models.Invitation(models.Model)

Invitation à rejoindre un tenant par email.

tenant: ForeignKey Tenant
email: EmailField
token: UUIDField(unique=True)

Token d’acceptation (envoyé par email).

roles: JSONField

Rôles pré-assignés à l’invité.

status: CharField

pending, accepted, declined, expired, cancelled.

invited_by: ForeignKey User
expires_at: DateTimeField

Méthodes :

accept(user) None

Accepte l’invitation. Crée la membership. Émet InvitationAccepted.

decline() None

Décline l’invitation.

cancel() None

Annule l’invitation (par l’émetteur).

is_expired() bool

Vérifie si l’invitation a expiré.