Aller au contenu principal

Modèle de données

Le schéma Prisma (prisma/schema.prisma) est la source unique de vérité pour le modèle de données. Cette page détaille les 30+ modèles centraux. Le schéma utilise PostgreSQL 18 et Prisma 5 avec soft delete sur certaines entités (deletedAt).

Modèles métier

Member

Représente un membre de l'association. Le champ role vaut adherent par défaut ; seuls animateur, formateur et les comptes isAdmin accèdent au Hub.

ChampTypeRôle
idString (CUID)Identifiant unique
emailString (unique)Email de connexion
firstName, lastNameStringIdentité
passwordHashString?Hash bcrypt (credentials auth)
genderString"masculin" / "feminin" / "neutre" (défaut) — appliqué aux templates emails
roleString"adherent" (défaut) / "animateur" / "formateur" — rôle pédagogique
isAdminBooleanAccès espace admin (false défaut) — indépendant du role
habilitationAnimationString?"grand_public" / "professionnelle" / null
habilitationFormationString?"grand_public" / "professionnelle" / null
habilitationExpiryDateTime?Date d'expiration habilitations
linkedinIdString? (unique)ID LinkedIn OAuth
linkedinUrl, websiteUrlString?URLs profil
avatarUrlString?URL avatar custom (fallback Gravatar)
bio, taglineString?Bio et phrase d'accroche « En une ligne »
locationString?Localisation
phoneString?Téléphone
badgesString[]IDs badges obtenus (dénormalisé pour perf)
directoryConsentBooleanOpt-in annuaire public
cotisationStatusString"inactive" (défaut) / "active" / "expired" — synchro HelloAsso webhook
cotisationExpiryDateTime?Date expiration cotisation
licenceTypeString?"professionnelle" / "citoyenne" / "interne" — "interne" exempt cotisation
invitationTokenString? (unique)Token invitation pour nouveaux membres
passwordResetTokenString? (unique)Token reset password (avec expiry)
createdAt, updatedAt, deletedAtDateTimeTimestamps (soft delete)

Relations : crée des Workshop, anime via WorkshopAnimator, rapports via UsageReport, badges via BadgeAssertion, gest. organisations via OrganisationManager, cotisations via CotisationPayment.

Workshop

Représente un atelier ou formation (public ou privé, grand public ou inter-organisations).

ChampTypeRôle
idString (CUID)Identifiant unique
slugString (unique)Slug URL publique
title, descriptionStringTitre et description
dateDateTimeDate/heure de début
durationIntDurée en minutes
eventTypeString"atelier" (défaut) / "formation"
typeStringType atelier technique (ex: "game", "discussion")
formatStringFormat (ex: "en_ligne", "presentiel", "hybride")
timezoneStringTimezone ("Europe/Paris" défaut)
languageString"fr" (défaut)
location, address, city, postalCode, region, departmentString?Adresse (autocompletée BAN)
themeString?Thème
targetPublicString"grand_public" (défaut) / "inter_organisations"
contextString?Contexte additionnel
capacityIntNombre de places
price, priceSolidaireHT, priceClassiqueHT, priceSoutienHTFloatPrix TTC et HT par tier (personnalisés par atelier)
statusString"draft" (défaut) / "published" / "cancelled"
createdByIdString?Animateur créateur (relation Member)
organisationIdString?Rattachement organisation (inter-organisations)
modelIdString?ID modèle plateau si atelier en ligne
waitlistEnabledBooleanListe d'attente active
privateRegistrationEnabledBooleanInscriptions privées (invités seuls)
createdAt, updatedAt, deletedAtDateTimeTimestamps (soft delete)

Relations : createdBy (Member), organisation (Organisation), animateurs via WorkshopAnimator, inscriptions via Registration, liste d'attente via WaitlistEntry, plateau via Board, résultats satisfaction via SatisfactionResponse, rapports utilisation via UsageReport, codes avantage via DiscountCode.

Registration

Représente l'inscription d'un participant à un atelier.

ChampTypeRôle
idString (CUID)Identifiant unique
workshopId, workshopString + FKAtelier
firstName, lastName, email, phoneStringDonnées participant
paymentStatusString"pending" (défaut) / "paid" / "refunded" / "voucher" / "blocked"
helloassoCheckoutIntentIdString?ID intention de paiement HelloAsso
helloassoOrderIdString?ID ordre HelloAsso (webhook)
amountHT, amountTTC, vatAmountFloatMontants facturés
discountCodeIdString?Code avantage appliqué
discountAmountHTFloatRéduction appliquée
invoiceUrlString?URL facture PDF
attendedBoolean?Présence pointée
participantIdString?Lien CRM Participant (créé/mis à jour au webhook)
cancellationTokenString? (unique)Token d'annulation public (lien email)
cancelledAtDateTime?Date annulation
refundMethodString?"refund" / "voucher" / "blocked" — décision remboursement
surveyTokenString? (unique)Token questionnaire satisfaction
surveySentAt, surveyRespondedAtDateTime?Envoi et réponse satisfaction
reminderSentAtDateTime?Rappel J-2 envoyé
createdAt, updatedAtDateTimeTimestamps
Unique[workshopId, email]Une seule inscription par email par atelier

Relations : workshop, participant (CRM), code avantage.

Participant

Représente un participant dans le CRM (déduplication par email).

ChampTypeRôle
idString (CUID)Identifiant unique
emailString (unique)Email de déduplication
firstName, lastName, phoneStringDonnées contact
tagsString[]Étiquettes texte libre (admin)
notesString?Notes internes admin
firstSeenAtDateTimePremière inscription enregistrée
createdAt, updatedAt, deletedAtDateTimeTimestamps (soft delete)

Relations : inscriptions via Registration, badges via BadgeAssertion.

WorkshopAnimator

Liaison N-N atelier ↔ animateur avec rôle (lead/co) et tracking « nouveaux inscrits ».

ChampTypeRôle
idString (CUID)Identifiant unique
workshopIdStringAtelier
memberIdStringAnimateur
roleString"lead" / "co" — lead = responsable
lastViewedAtDateTimeTimestamp dernière visite fiche atelier → déclenche le badge "nouveaux inscrits"
Unique[workshopId, memberId]Un seul rôle par animateur par atelier

Organisation

Fiches organisation pour ateliers inter-organisations (lookup SIRET auto).

ChampTypeRôle
idString (CUID)Identifiant unique
nameString (unique)Nom organisation
typeString?Type (entreprise, association, etc.)
siretString? (unique)SIRET (lookup API recherche-entreprises)
address, city, postalCodeString?Adresse
notesString?Notes internes
createdAt, updatedAtDateTimeTimestamps

Relations : ateliers via Workshop, gestionnaires via OrganisationManager.

OrganisationManager

Liaison N-N organisation ↔ membre (gestionnaire).

ChampTypeRôle
idString (CUID)Identifiant unique
organisationId, memberIdStringOrganisation et gestionnaire
createdAtDateTimeTimestamp
Unique[organisationId, memberId]Un seul rôle gestionnaire par membre par org

WaitlistEntry

Liste d'attente pour ateliers complets.

ChampTypeRôle
idString (CUID)Identifiant unique
workshopId, workshopString + FKAtelier
firstName, lastName, email, phoneStringDonnées
positionIntPosition dans la file
notifiedAtDateTime?Notification d'ouverture de place
createdAtDateTimeTimestamp
Unique[workshopId, email]Une seule entrée par email par atelier

CotisationPayment

Paiements de cotisation tracés (source HelloAsso).

ChampTypeRôle
idString (CUID)Identifiant unique
memberId, memberString + FKAdhérent
helloassoOrderIdString (unique)ID ordre HelloAsso
licenceTypeStringLicence achetée (professionnelle / citoyenne / interne)
amountCentsIntMontant en centimes
paidAtDateTimeDate paiement
createdAtDateTimeTimestamp

BadgeAssertion

Badges Open Badges 3.0 (VerifiableCredential JWT signé EdDSA).

ChampTypeRôle
idString (CUID)Identifiant unique
typeString"ANIMATOR_PUBLIC" / "ANIMATOR_PRO" / "TRAINER_PUBLIC" / "TRAINER_PRO" / "PARTICIPANT"
memberId, participantIdString?Bénéficiaire (Member ou Participant)
recipientEmail, recipientNameStringDonnées pour assertion
signedJwtString (Text)JWT EdDSA signé (VerifiableCredential OB3)
issuedAtDateTimeDate émission
revokedBooleanRévocation
createdAtDateTimeTimestamp

UsageReport

Déclarations de droits d'utilisation professionnels (rapports pédagogiques).

ChampTypeRôle
idString (CUID)Identifiant unique
memberId, workshopIdStringAnimateur et atelier référence
usageContext, organisationName, participantCountStringContexte d'utilisation
amountHT, amountTTCFloatMontants facturés
paymentStatusString"pending" / "paid"
helloassoCheckoutIntentId, helloassoOrderIdString?Traçabilité paiement HelloAsso
invoiceUrlString?URL facture
createdAt, updatedAtDateTimeTimestamps

Article

Actualités du Hub (publiées sur LeSite).

ChampTypeRôle
idString (CUID)Identifiant unique
slugString (unique)Slug URL
title, excerpt, bodyStringContenu Markdown GFM
categoryStringCatégorie article
authorName, authorRoleStringAuteur (dropdown admin)
imageUrl, imageCaptionString?Image et légende (upload → WebP)
publishedBooleanPublication
publishedAtDateTime?Date publication
wordCountIntNombre de mots
createdAt, updatedAtDateTimeTimestamps

Resource

Médiathèque (articles, livres, podcasts, vidéos, rapports).

ChampTypeRôle
idString (CUID)Identifiant unique
title, descriptionStringTitre et description
typeString?Type (article, book, podcast, video, report)
themesString[]Thématiques (multi-select)
categoryString"documentaire" (défaut)
workshopTypeString?Type atelier associé
authorsString[]Auteurs
dateDateTime?Date publication
languageLinks, titleLinksJsonTraductions et liens par langue
isPublicBooleanVisibilité
createdAtDateTimeTimestamp

PedagogicalVersion

Supports pédagogiques versionnés (section + slot, accès animateur/formateur).

ChampTypeRôle
idString (CUID)Identifiant unique
section, slotStringSection et slot (ex: "formation", "1")
versionStringVersion (ex: "v1.0")
linkStringURL ressource
dateDateTime?Date version
accessString"animateur" (défaut) / "formateur"
isCurrentBooleanVersion courante
notesString?Notes
createdAtDateTimeTimestamp

DiscountCode

Codes avantage (réduction % ou montant fixe).

ChampTypeRôle
idString (CUID)Identifiant unique
codeString (unique)Code (ex: "NOEL20")
percentOff, amountOffTTCInt/Float?Réduction (l'une ou l'autre)
maxUsesInt?Limite d'utilisations
workshopIdString?Restriction à un atelier (optionnel)
restrictedToEmailString?Restriction email (optionnel)
expiresAtDateTime?Expiration
activeBooleanActivité
createdAt, updatedAtDateTimeTimestamps

SatisfactionResponse

Réponses au questionnaire post-atelier.

ChampTypeRôle
idString (CUID)Identifiant unique
workshopId, workshopString + FKAtelier
answersJsonRéponses structurées (JSON)
commentString?Commentaire libre
submittedAtDateTimeDate réponse

Settings

Paramètres globaux (singleton, id='global').

ChampTypeRôle
idString"global" (unique)
workshopModerationOnBooleanFlag modération ateliers
siteChantierModeBooleanMode chantier site public
priceInterneHT, pricePrestationHT, vatRateFloatTarifications legacy
priceSolidaireHT, priceClassiqueHT, priceSoutienHTFloatPrix par défaut (legacy, overridable par PricingPolicy)
IdentitéassociationName, logoPath, address, postalCode, city, contactEmailInfos association
Mentions légalessiret, rna, tvaNumber, tvaApplicableDonnées légales
EmailemailFrom, emailFromName, emailReplyTo, resendApiKeyConfig Resend
HelloAssohelloassoClientId, helloassoClientSecret, helloassoOrgSlug, helloassoEnvIdentifiants HelloAsso (prod)
helloassoSandboxClientId, helloassoSandboxClientSecret, helloassoSandboxOrgSlugIdentifiants HelloAsso (sandbox)
helloassoRefundEnabledRemboursement HelloAsso auto (en attente privilège RefundManagement)
TelegramtelegramBotToken, telegramChatIdNotifs admin
Logo.devlogoDevPublishableKey, logoDevSecretKeyAPI Logo.dev (signatures digitales optionnel)
emailsEnabledJson?Toggle activation/désactivation des templates emails
updatedAtDateTimeTimestamp

PricingPolicy

Tarification par eventType × publicType (matrice 3-tiers).

ChampTypeRôle
idString (CUID)Identifiant unique
eventType, publicTypeStringClés (ex: "atelier", "grand_public")
solidaireHT, classiqueHT, soutienHTFloatPrix par tier
Unique[eventType, publicType]Une seule politique par combinaison

FormatPricing

Prix hors taxes par format d'atelier. Table d'appoint très simple, distincte de PricingPolicy : là où PricingPolicy croise un type d'événement et un type de public pour produire trois tarifs, FormatPricing associe un prix unique à un format.

ChampTypeRôle
idString (CUID)Identifiant unique
formatStringFormat d'atelier, unique
priceHTFloatPrix hors taxes pour ce format

Relations : aucune. La table est lue par clé format.

NotificationConfig

Configuration notifications email/Telegram par type d'événement admin.

ChampTypeRôle
idString (CUID)Identifiant unique
eventTypeString (unique)Type événement (ex: "rapport_utilisation")
emailEnabled, telegramEnabledBooleanCanaux actifs

Liaisons OAuth LinkedIn en attente (TTL 15 min).

ChampTypeRôle
idString (CUID)Identifiant unique
tokenString (unique)Token lien
linkedinId, linkedinName, linkedinEmailStringDonnées LinkedIn
expiresAtDateTimeExpiration
createdAtDateTimeTimestamp

WorkshopModel

Modèles de plateau LeBoard.

ChampTypeRôle
idString (CUID)Identifiant unique
nameStringNom modèle
languageString"fr" (défaut)
plateauIdString?ID plateau LeBoard (ref)
createdAt, updatedAtDateTimeTimestamps

Relations : lots via Lot, boards via Board, titres cartes via ModelCardTitle.

Lot

Lots de cartes d'un modèle plateau.

ChampTypeRôle
idString (CUID)Identifiant unique
modelId, modelString + FKModèle
nameStringNom lot
orderIntOrdre
stageIdString?ID étape LeBoard
kindString?Type lot
cardIdsStringIDs cartes (JSON ou CSV)
contentTypeString"cards" (défaut) / "slides"
slidesDataString?Données diapositives

Relations : distributions via BoardLotDistribution.

Board

Plateau en ligne d'un atelier (propriété LeBoard, accès en écriture du Hub).

ChampTypeRôle
idString (CUID)Identifiant unique
workshopIdString (unique)Atelier
workshopTitleStringTitre (dénormalisé)
tokenString (unique)Token d'accès
languageString"fr" (défaut)
statusString"active" (défaut)
isTrainingBooleanAtelier test (24h expiration)
expiresAtDateTime?Expiration
modelIdString?Modèle plateau
activeStageIdStringID étape active (persisté pour redémarrage)
createdAt, updatedAtDateTimeTimestamps

Relations : placements via CardPlacement, connexions via Connection, distributions via BoardLotDistribution, sessions via AnimatorSession.

CardPlacement

Positionnement d'une carte sur un plateau.

ChampTypeRôle
idString (CUID)Identifiant unique
boardId, cardIdStringPlateau et ID carte
x, yFloatCoordonnées
rotationFloatRotation en degrés
zIndexIntProfondeur
flippedBooleanVerso retourné
updatedAtDateTimeTimestamp

Connection

Flèche/connexion entre cartes sur un plateau.

ChampTypeRôle
idString (CUID)Identifiant unique
boardIdStringPlateau
fromId, toIdStringCartes source/destination
labelString?Label flèche
createdAtDateTimeTimestamp

AnimatorSession

Sessions SSO animateur (token signé, TTL).

ChampTypeRôle
idString (CUID)Identifiant unique
boardId, memberIdStringPlateau et animateur
pseudoStringPseudonyme animateur
expiresAtDateTimeExpiration session
createdAtDateTimeTimestamp

ModelCardTitle

Titres de cartes personnalisés par modèle.

ChampTypeRôle
idString (CUID)Identifiant unique
workshopModelId, cardIdStringModèle et ID carte
customTitleStringTitre personnalisé
Unique[workshopModelId, cardId]Un seul titre par carte par modèle

BoardLotDistribution

Distribution des lots sur un plateau (timestamp + mode de lancement).

ChampTypeRôle
idString (CUID)Identifiant unique
boardId, lotIdStringPlateau et lot
modeString"distribute" (défaut) / "popcorn"
distributedAtDateTimeTimestamp distribution
Unique[boardId, lotId]Un seul record par lot par plateau

CardMeta

Titres de cartes personnalisés legacy (hors modèle).

ChampTypeRôle
idString (CUID)Identifiant unique
cardIdStringID carte
languageStringLangue
customTitleString?Titre personnalisé
Unique[cardId, language]Un seul titre par carte par langue

Diagramme ER (flux principaux)