Architecture Sessions, Collaborateurs & Moodboards
Document de référence pour comprendre le modèle centré sessions avec collaborateurs et moodboards.
Changelog docs
- 2026-02-18: Suppression du concept "Projet". Les collaborateurs et moodboards sont rattachés directement aux sessions. Simplification des rôles (VIEWER/EDITOR/ADMIN).
- 2026-02-18: Mise à jour moodboards - images uniquement, upload multiple (max 10), niveau session.
- 2026-02-18: Simplification moodboard - un seul moodboard par session (auto-créé), routes sans :moodboardId pour les items.
- 2026-02-19: Migration des droits client moodboard vers
client_access_level(NONE/READ/READ_WRITE). Suppression deis_shared_with_clientetclient_can_edit. - 2026-02-19: Reorder drag & drop + suppression exposés côté client authentifié (
/client-accounts/me/...) quand le moodboard est enREAD_WRITE. - 2026-02-19: Reorder moodboard en UI optimiste (user/client/portal) + synchro temps réel via websocket
moodboard:updated.
1. Vision
1.1 Modèle centré Sessions
- La session est l'unité centrale de travail.
- Les objets métier (collaborateurs, moodboards, documents, paiements, workflows, fichiers) se rattachent à la session.
- Il n'y a pas de couche "projet" intermédiaire. Les photographes et prestataires pensent en "séances", pas en "projets".
2. Principes fonctionnels
- Session d'abord : chaque prestation est une session avec son contexte (date, lieu, type, contact, statut).
- Collaboration directe : les collaborateurs sont invités au niveau de la session.
- Moodboard par session : chaque session a un moodboard unique (auto-créé) avec des images.
- Documents liés : devis, factures, contrats sont rattachés à la session via le contact.
3. Entités et relations
3.1 Entités
sessions: Sessions photographiques (mariages, séances, événements)session_collaborators: Collaborateurs invités sur une sessionsession_moodboards: Moodboards de session (partageables avec le client)session_moodboard_items: Éléments de moodboard (images uniquement)session_contacts: Relations sessions ↔ contactssession_tags: Tags associés aux sessionssession_providers: Prestataires associés (traiteurs, DJ, etc.)session_checklists/session_checklist_items: Checklists de sessionsession_files: Fichiers associés à une sessionsession_planning_items: Items de planification (roadmap)quotes/contracts/invoices/payments: Documents financiers liés au contact de la session
3.2 Relations
session 1 -> N session_collaboratorssession 1 -> 1 session_moodboard(fonctionnellement unique par owner/session)session_moodboard 1 -> N session_moodboard_itemssession 1 -> N quotes/contracts/invoices(via contact)session 1 -> N session_filessession 1 -> N session_providers
4. Collaborateurs
4.1 Identification
Chaque collaborateur est identifié par exactement un des trois moyens :
collaborator_user_id: un utilisateur Aaperture existantinvited_email: une adresse email (invitation en attente)linked_provider_id: un prestataire lié (user_providers)
4.2 Rôles simplifiés
| Rôle | Description |
|---|---|
VIEWER | Lecture seule sur la session |
EDITOR | Lecture + modification |
ADMIN | Accès complet (comme le owner) |
4.3 Flux d'invitation
- Owner invite un collaborateur sur une session.
- Statut initial :
PENDING. - Collaborateur accepte (
ACCEPTED) ou refuse (DECLINED). - Possibilité de renvoyer l'invitation.
4.4 API
GET /sessions/:sessionId/collaboratorsPOST /sessions/:sessionId/collaboratorsPATCH /sessions/:sessionId/collaborators/:idDELETE /sessions/:sessionId/collaborators/:idPOST /sessions/:sessionId/collaborators/:id/resend-invite
5. Moodboard
5.1 Principes
- Chaque session a un seul moodboard (auto-créé à l'ajout du premier item).
- Le moodboard contient uniquement des images (upload multiple, max 10 à la fois).
- Le partage client est piloté par
client_access_level:NONE: non partagéREAD: lecture seuleREAD_WRITE: lecture + upload + suppression + reorder côté client
- Les items supportent une catégorie optionnelle pour organiser les images.
- Le frontend affiche directement la grille d'images, sans liste intermédiaire de moodboards.
- Le reorder est en drag & drop avec optimistic update (pas de retour visuel en arrière pendant la persistance).
- Les changements moodboard déclenchent un event websocket
moodboard:updatedpour invalider/refetch côté user et client.
5.2 API photographe
GET /sessions/:sessionId/moodboards— retourne le moodboard unique (objet) ounullPUT /sessions/:sessionId/moodboards— créer/mettre à jour les paramètres du moodboard (title,description,client_access_level)DELETE /sessions/:sessionId/moodboards— supprimer le moodboard et tous ses itemsPOST /sessions/:sessionId/moodboards/upload-image— upload une imagePOST /sessions/:sessionId/moodboards/upload-images— upload multiple (max 10)POST /sessions/:sessionId/moodboards/items— ajouter un item (auto-crée le moodboard)PATCH /sessions/:sessionId/moodboards/items/:itemId— modifier un itemDELETE /sessions/:sessionId/moodboards/items/:itemId— supprimer un item
5.3 API client
5.3.1 Lien sécurisé (token client-access)
GET /client-access/sessions/:sessionId/moodboards— retourne le moodboard partagé (objet) ounullPOST /client-access/sessions/:sessionId/moodboards/items— ajouter un itemPATCH /client-access/sessions/:sessionId/moodboards/items/:itemId— modifier un itemDELETE /client-access/sessions/:sessionId/moodboards/items/:itemId— supprimer un itemPOST /client-access/sessions/:sessionId/moodboards/upload-image— upload une imagePOST /client-access/sessions/:sessionId/moodboards/upload-images— upload multiple (max 10)
5.3.2 Portail client authentifié (client-accounts)
GET /client-accounts/me/sessions/:sessionId/moodboard— retourne le moodboard partagé (objet) ounullPATCH /client-accounts/me/sessions/:sessionId/moodboard/items/:itemId— update item (reorder/catégorie/image), autorisé enREAD_WRITEDELETE /client-accounts/me/sessions/:sessionId/moodboard/items/:itemId— suppression item, autorisée enREAD_WRITE
6. Vue session (onglets)
La page de détail d'une session comporte les onglets suivants :
- Vue d'ensemble : résumé, statut, contact, prochaines actions
- Préparation : checklist, tâches, workflow
- Logistique : planning, roadmap, météo
- Documents : fichiers liés
- Finances : devis, factures, paiements
- Suivi client : contact, relances, historique
- Équipe : collaborateurs invités + prestataires
- Moodboard : moodboard et images
7. Portail client
7.1 Routes
/portal/sessions— liste des séances du client/portal/sessions/:sessionId— détail d'une séance/portal/documents— documents (devis, factures, contrats)/portal/galleries— galeries photos/portal/messages— messagerie/portal/files— fichiers partagés
7.2 API client
GET /client-accounts/me/sessions— liste des sessions du clientGET /client-accounts/me/sessions/:sessionId— détail d'une sessionGET /client-accounts/me/sessions/:sessionId/moodboard— moodboard de session partagéPATCH /client-accounts/me/sessions/:sessionId/moodboard/items/:itemId— mise à jour item (siREAD_WRITE)DELETE /client-accounts/me/sessions/:sessionId/moodboard/items/:itemId— suppression item (siREAD_WRITE)GET /client-accounts/me/documents— documents du clientGET /client-accounts/me/photographers— photographes liés
8. Tables DB
session_collaborators
CREATE TABLE session_collaborators (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
collaborator_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
invited_email VARCHAR(255),
linked_provider_id UUID REFERENCES user_providers(id) ON DELETE SET NULL,
role VARCHAR(50) NOT NULL DEFAULT 'VIEWER'
CHECK (role IN ('VIEWER', 'EDITOR', 'ADMIN')),
invitation_status VARCHAR(50) NOT NULL DEFAULT 'PENDING'
CHECK (invitation_status IN ('PENDING', 'ACCEPTED', 'DECLINED')),
invited_by_user_id UUID REFERENCES users(id),
invited_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
accepted_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT exactly_one_identifier CHECK (
(collaborator_user_id IS NOT NULL)::int +
(invited_email IS NOT NULL)::int +
(linked_provider_id IS NOT NULL)::int = 1
)
);
session_moodboards + session_moodboard_items
CREATE TABLE session_moodboards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL DEFAULT 'Moodboard',
description TEXT,
client_access_level VARCHAR(20) NOT NULL DEFAULT 'NONE'
CHECK (client_access_level IN ('NONE', 'READ', 'READ_WRITE')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE session_moodboard_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
moodboard_id UUID NOT NULL REFERENCES session_moodboards(id) ON DELETE CASCADE,
created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('IMAGE', 'LINK', 'NOTE')),
image_url TEXT,
external_url TEXT,
note TEXT,
category VARCHAR(100),
display_order INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);