Entités Utilisateurs
User
Table : users
Description : Représente un utilisateur dans le système (étudiant, enseignant, admin, etc.)
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
firstname |
string |
Prénom de l'utilisateur (max 200 caractères) | profile.firstName |
lastname |
string |
Nom de famille de l'utilisateur (max 200 caractères, non sélectionné par défaut) | profile.lastName |
fullname |
string |
Nom complet généré automatiquement (prénom + nom) | - |
resetPasswordOngoing |
boolean |
Indique si une réinitialisation de mot de passe est en cours (défaut: false) | - |
birthdate |
Date |
Date de naissance de l'utilisateur | profile.birthDate |
zipcode |
string |
Code postal de l'utilisateur (max 200 caractères) | profile.codePostal |
phoneNumber |
string \| null |
Numéro de téléphone (max 200 caractères), saisi dans le profil éclaireur ou le formulaire MVLS. Non sélectionné par défaut (select: false) : chargé seulement si la requête le demande (select: { phoneNumber: true } ou addSelect). Visible par le titulaire et l'admin. Le lycéen le voit sur la fiche mentorat de son mentor, pas sur le profil public, la recherche, les favoris ni le chat. Le numéro du lycéen est chargé pour l'éclaireur sur son binôme. Synchronisé vers Dema1n. |
phoneNumber |
foreign |
boolean |
Indique si l'utilisateur est étranger (défaut: false) | profile.foreign |
gender |
enum |
Genre de l'utilisateur | profile.gender (mappé) |
flaggedForModeration |
string |
Raison du signalement pour modération (V1, max 200 caractères) | profile.flaggedForModeration |
newsletter |
boolean |
Abonnement à la newsletter (défaut: false) | profile.newsletter |
roles |
enum[] |
Rôles de l'utilisateur (tableau) | profile.role (mappé) |
savedData |
jsonb |
Données sauvegardées de la V1 (non sélectionné par défaut) | Voir détails ci-dessous |
picture |
string |
URL de la photo de profil (max 1000 caractères) | profile.picture |
status |
string \| null |
Visibilité de l'éclaireur : null si l'user n'est pas éclaireur. caché par défaut à la création, visible dès que l'EE a un profil complet (photo + parcours pour l'année en cours). Seul le cron annuel de rentrée peut le repasser caché (aucun parcours depuis 2 ans). |
profile.status |
passageEclaireurAt |
Date |
Date de passage au statut éclaireur | profile.passageEclaireurAt |
isGuideAccepted |
boolean |
Indique si le guide a été accepté (défaut: false) | - |
isProfileComplete |
boolean \| null |
Profil éclaireur complet : null = pas éclaireur, false = éclaireur profil incomplet, true = éclaireur avec photo + parcours année en cours. Reset annuel au 1er août. |
isProfileComplete |
isElasticVerified |
boolean |
Indique si l'utilisateur est vérifié dans Elasticsearch (défaut: false) | - |
mvls |
enum \| null |
Facultatif. null = n'a jamais commencé d'inscription MVLS. mvls = a commencé son inscription MVLS (dès le début du questionnaire, ou ajout manuel) — ne suffit pas à qualifier d'inscrit (seul charte === true fait foi, voir docs/mvls/index.md). refused = a refusé le programme. banned = banni suite à un USER_DELETED reçu de DEMA1N. |
- |
hasSeenMvlsPopup |
boolean |
Défaut false. true = a vu ou fermé la popup d'invitation mentor MVLS (éclaireurs éligibles) |
- |
hasSeenMvlsPrioPopup |
boolean |
Défaut false. true = a vu ou fermé la popup d'invitation MVLS lycéens prioritaires |
- |
origineInscriptionMvls |
enum \| null |
Facultatif. Origine du parcours d'inscription MVLS. null = inconnue. atelier_mvls = posé après le retour SSO uniquement si l'URL contient le query param atelier (entrée /inscription-mvls-ateliers) — voir docs/mvls/index.md |
- |
has_accepted_bv_charte |
boolean \| null |
Obligatoire pour les EE inscrits après 08/26. Indique si l'utilisateur a accepté la charte des bénévoles (null pour les utilisateurs créés avant ajout du champ et avant inscription, après : true pour les EE inscrits, false pour les lycéens) |
- |
deleteAccountReason |
enum \| null |
Facultatif. Raison de suppression de compte choisie par l'utilisateur | - |
deleteAccountOtherText |
string \| null |
Facultatif. Raison détaillée si deleteAccountReason = other (max 200 caractères) |
- |
notifiedObsoleteJulyAt |
Date \| null |
Date d'envoi de l'email d'avertissement (archivage 27 ans, juillet). Permet de rejouer la tâche sans renotifier les users déjà avertis | - |
notifiedObsoleteAugustAt |
Date \| null |
Date d'envoi de l'email final (archivage 27 ans, août). Permet de rejouer la tâche sans renotifier les users déjà avertis | - |
niveau |
enum \| null |
Niveau du lycéen. null = non applicable. MAJ auto via questionnaire lycéen et crons de passage de niveau — voir docs/metier/niveau.md |
- |
Valeurs possibles pour deleteAccountReason (DeleteAccountReasonEnum) :
found_all_answers: A trouvé toutes ses réponsestoo_many_emails: Trop d'emailsmisunderstood_site: N'a pas compris le siteother: Autre (voirdeleteAccountOtherText)
Valeurs possibles pour niveau (UserNiveauEnum) :
Seconde,Première,Terminale,En transition,Post-bac
Valeurs possibles pour gender (GenderEnum) :
male: Masculinfemale: Fémininother: Autreno_answer: Sans réponse
Valeurs possibles pour roles (UserRoleEnum[]) :
admin: Administrateuruser: Utilisateur standardlyceen: Lycéeneclaireur: Éclaireursso-registered: Enregistré via SSOpedagogie: Pédagogieworker: Worker
Valeurs possibles pour mvls (UserMvlsEnum) :
null: n'a jamais commencé d'inscription MVLSmvls: a commencé son inscription MVLS (questionnaire commencé, ou ajout manuel). ≠ inscrit — l'inscription effective estMvlsLyceen.charte === true/MvlsEclaireur.charte === truerefused: a refusé le programme (poursuivreEtudes === falsedans le questionnaire lycéen, ouPOST /mvls-lyceen/refuse)banned: banni — posé à la réception d'unUSER_DELETEDDEMA1N (MessageQueuingService.deleteUserMvls)
Valeurs possibles pour origineInscriptionMvls (UserOrigineInscriptionMvlsEnum) :
atelier_mvls: inscription via la page ateliers (/inscription-mvls-ateliers→ SSO vers/mentorat?atelier)null: origine inconnue (retour Mentorat hors ateliers, cas 1 déjà connecté, etc.)
Valeurs possibles pour status (UserStatusEnum) — uniquement pour les éclaireurs :
caché: par défaut à la création ; l’EE n’apparaît pas dans la recherchevisible: l’EE a complété son inscription (photo + parcours pour l’année en cours) ; seuls les éclaireursvisiblesont affichés aux lycéensinactif: non utilisé automatiquement — réservé à un usage manuel
Transitions automatiques :
caché→visible: à la fin de l’inscription éclaireur (photo + parcours validés)visible→caché: cron annuel du 1er août (hideInactiveEclaireursForNewSchoolYear) si aucun parcours-éclaireur sur les 2 dernières années scolaires ;isElasticVerifiedrepasse àfalsepour désindexation
Champs savedData (JSON) :
stateOfMind:stateOfMindactivitesBacPro:activitesBacProcurrentClasseId:currentClasseIdsavedParcoursLyceenData: Données de parcours lycéen sauvegardéessavedParcoursEclaireurData: Données de parcours éclaireur sauvegardées
Relations :
tags: Tags créés par l'utilisateurparcoursLyceens: Parcours lycéen de l'utilisateurparcoursEclaireurs: Parcours éclaireur de l'utilisateurmvlsEclaireur: MVLS éclaireur de l'utilisateur (relation one-to-one — un utilisateur ne peut avoir qu'un seulMvlsEclaireur, voir entities/mvls.md)mvlsLyceen: MVLS lycéen de l'utilisateur (relation one-to-one — un utilisateur ne peut avoir qu'un seulMvlsLyceen, voir entities/mvls.md)userJwt: Informations d'authentificationcomments: Commentaires postés par l'utilisateurmedias: Médias créés par l'utilisateurchatChannels: Canaux de chat de l'utilisateuruserImpacts: Impacts utilisateur (avis sur pistes/articles)
UserNiveauHistory
Table : user-niveau-history
Description : Historique des passages de niveau scolaire d'un lycéen (append-only, aucune mise à jour ni suppression). N'hérite pas de BaseEntity : pas de updatedAt/deletedAt, seulement id + createdAt. Pas de relation TypeORM formelle vers User — userId est une simple colonne indexée, jointure à faire manuellement.
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique | - |
createdAt |
Date |
Date du passage (timestamptz) | - |
userId |
number |
ID de l'utilisateur concerné (indexé) | - |
oldNiveau |
enum \| null |
Niveau avant transition (null si premier passage renseigné) |
- |
newNiveau |
enum |
Niveau après transition | - |
reason |
enum |
Origine de la transition | - |
Valeurs possibles pour oldNiveau/newNiveau (UserNiveauEnum) :
Seconde,Première,Terminale,En transition,Post-bac
Valeurs possibles pour reason (UserNiveauReasonEnum) :
questionnaire: mise à jour en temps réel via le formulaire parcours-lycéencron_aout: cron annuel du 1er août (progression Seconde→Première→Terminale→En transition)cron_decembre: cron du 1er décembre (En transition→Post-bac, lycéens non-MVLS)cron_janvier: cron du 10 janvier (En transition→Post-bac, lycéens MVLS matchés)backfill: backfill one-shot (copie depuis parcours-lycéen ou forçage pré-plateforme)admin: modification manuelle via l'outil de recette/admin/niveau
Voir docs/metier/niveau.md pour la logique complète (crons, backfill, outils de recette).
UserJwt
Table : user-jwt
Description : Informations d'authentification et de sécurité des utilisateurs
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
username |
string |
Nom d'utilisateur unique (max 255 caractères) | username |
ssoId |
string |
Identifiant SSO pour liaison avec l'app A1C (max 4055 caractères) | ssoId |
password |
string |
Mot de passe hashé (non sélectionné par défaut, max 255 caractères). L'API ne le lit plus : la connexion passe par A1Connect | services.password.bcrypt |
activated |
boolean |
Accès du compte. Défaut false. Voir « Comptes à activer au lancement » |
emails[0].verified |
activationToken |
string |
Token d'activation (non sélectionné par défaut, max 255 caractères) | - |
lastLogin |
Date |
Date de dernière connexion | lastLogin |
oldId |
string |
Identifiant de l'ancienne base de données (max 200 caractères) | _id |
referredBy |
string |
Référent de l'utilisateur | - |
lastDayOfActivity |
Date |
Dernier jour d'activité | lastDayOfActivity |
forgetPasswordToken |
string |
Token de réinitialisation de mot de passe (non sélectionné par défaut, max 255 caractères). Plus utilisé depuis le retrait de la récupération de mot de passe | - |
forgetPasswordExpiresAt |
timestamptz \| null |
Expiration du lien de récupération. Plus utilisé depuis le retrait de la récupération de mot de passe | - |
Comptes à activer au lancement
Un lycéen, un admin, un compte pédagogie ou un worker encore activated = false ne peut pas se connecter : le mot de passe est refusé, et un JWT déjà émis est refusé au refresh, sur les routes JWT et sur le flux SSE.
activated = false reste normal pour un éclaireur qui n'a pas confirmé son e-mail : sa session reste ouverte. Un compte sans rôle lycéen, admin, pédagogie ou worker est encore dans l'inscription : sa session reste ouverte aussi.
Deux migrations préparent les comptes existants. Elles passent avec yarn migration:run, comme les autres :
1790899200000-forget-password-token-expiryajouteforgetPasswordExpiresAt. Elle ne modifie pasactivated.1791200000000-activate-roles-requiring-activationpasseactivatedàtruepour les lycéens, admins, pédagogie et workers non supprimés, hors éclaireurs. Elle n'a pas de retour arrière : redésactiver ces comptes couperait l'accès de comptes en usage.
Sur une grosse base, la seconde migration fait un seul UPDATE sur user-jwt joint à users. Elle peut prendre du temps : laisser le job de migration aller au bout.
Etablissement
Table : etablissements
Description : Représente un établissement scolaire en France
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
old_id |
string |
Identifiant de l'ancienne base de données (max 255 caractères) | _id |
nom |
string |
Nom de l'établissement (max 255 caractères) | nom (lycées) / name (supérieur) |
typeEtablissement |
enum[] |
Types d'établissement (tableau) | typeEtablissement (lycées) / ['superieur'] (supérieur) |
ville |
string |
Ville de l'établissement (max 127 caractères) | ville (lycées) / commune (supérieur) |
academie |
string |
Académie de l'établissement (max 127 caractères) | academie |
departementCode |
string |
Code du département (max 8 caractères) | departementCode (lycées) / departement (supérieur, extrait) |
codePostal |
string |
Code postal (max 32 caractères) | codePostal (lycées) / cp (supérieur) |
adresse |
string |
Adresse complète (max 255 caractères) | adresse |
isPrioritaire |
boolean |
Indique si l'établissement est prioritaire | isPrioritaire (lycées) / null (supérieur) |
codeUai |
string |
Code établissement UAI (max 32 caractères) | uai_ips (lycées) / code_uai (supérieur) |
universiteDeRattachement |
string |
Université de rattachement (max 255 caractères) | null (lycées) / universite (supérieur) |
idEtablissementOnisep |
string |
Identifiant établissement Onisep (max 127 caractères) | null (lycées) / idEtablissementOnisep (supérieur) |
isDenied |
boolean |
Indique si l'établissement est refusé | - |
isPartenaire |
boolean |
Indique si l'établissement est partenaire | - |
referentielUuid |
uuid |
Identifiant établissement Article1Connect ) | - |
toCheck |
boolean |
Indique si il faut vérifier que le referentielUuid correspond bien à l'établissement inspire | - |
Valeurs possibles pour typeEtablissement (TypeEtablissementEnum[]) : |
lycee: Lycéesuperieur: Supérieur
Relations :
parcoursLyceens: Parcours lycéens de cet établissementparcoursEclaireurs: Parcours éclaireurs de cet établissementformations: Formations proposées par cet établissement
Formation
Table : formations
Description : Représente une formation proposée par un établissement
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
nom |
string |
Nom de la formation (max 255 caractères) | - |
idFormationOnisep |
string |
ID formation Onisep (max 32 caractères) | - |
typeFormation |
enum[] |
Types de formation (tableau) | - |
old_id |
string |
Identifiant de l'ancienne base de données (max 255 caractères) | - |
Valeurs possibles pour typeFormation (TypeFormationEnum[]) :
Bachelor Universitaire de Technologie (BUT): BUTBrevet de Technicien Supérieur (BTS): BTSCertificat de Spécialisation (CS): CSClasse Préparatoire aux Grandes Ecoles (CPGE): CPGEDiplôme d'Etudes Universitaires Scientifiques et Techniques (DEUST): DEUSTEcole post-bac: École post-bacFormation Complémentaire d'Initiative Locale (FCIL): FCILInsertion: InsertionLicence: LicenceAutre: Autre
Relations :
etablissement: Établissement proposant cette formation
ContactsEquipePedagogique
Table : contacts-equipe-pedagogique
Description : Contacts de l'équipe pédagogique
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
email |
string |
Adresse email (max 200 caractères) | - |
UserImpact
Table : user-impact
Description : Représente les avis/impacts des utilisateurs sur les pistes et articles
| Champ | Type | Description | Champ BigQuery |
|---|---|---|---|
id |
number |
Identifiant unique (hérité de BaseEntity) | - |
popupType |
enum |
Type de popup pour laquelle l'avis a été donné | - |
comprisPiste |
string |
Avis sur la compréhension de la piste | - |
suivrePiste |
string |
Avis sur le suivi de la piste | - |
connaitrePiste |
string |
Connaissance de cette formation | - |
conseilsUtiles |
string |
Avis sur l'utilité des conseils | - |
mieuxPrepares |
string |
Avis sur la préparation | - |
informationsUtiles |
string |
Avis sur l'utilité des informations | - |
ouDemander |
string |
Avis sur où demander | - |
accordClassement |
string |
Accord avec le classement | - |
raison_accord_classement |
string |
Facultatif. Réponse à la question Pourquoi ? dans la pop up Que penses-tu des pistes recommandées ? | - |
pisteId |
number |
ID de la piste associée (si applicable) | - |
articleId |
number |
ID de l'article associé (si applicable) | - |
Valeurs possibles pour popupType (PopupType) :
avis_piste: Avis sur une pisteavis_article_orientation: Avis sur un article d'orientationavis_article_vie: Avis sur un article de vie étudianteavis_reco_pistes: Avis sur les recommandations de pistes
Relations :
user: Utilisateur associépiste: Piste associée (si applicable)article: Article associé (si applicable)