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éponses
  • too_many_emails : Trop d'emails
  • misunderstood_site : N'a pas compris le site
  • other : Autre (voir deleteAccountOtherText)

Valeurs possibles pour niveau (UserNiveauEnum) :

  • Seconde, Première, Terminale, En transition, Post-bac

Valeurs possibles pour gender (GenderEnum) :

  • male : Masculin
  • female : Féminin
  • other : Autre
  • no_answer : Sans réponse

Valeurs possibles pour roles (UserRoleEnum[]) :

  • admin : Administrateur
  • user : Utilisateur standard
  • lyceen : Lycéen
  • eclaireur : Éclaireur
  • sso-registered : Enregistré via SSO
  • pedagogie : Pédagogie
  • worker : Worker

Valeurs possibles pour mvls (UserMvlsEnum) :

  • null : n'a jamais commencé d'inscription MVLS
  • mvls : a commencé son inscription MVLS (questionnaire commencé, ou ajout manuel). ≠ inscrit — l'inscription effective est MvlsLyceen.charte === true / MvlsEclaireur.charte === true
  • refused : a refusé le programme (poursuivreEtudes === false dans le questionnaire lycéen, ou POST /mvls-lyceen/refuse)
  • banned : banni — posé à la réception d'un USER_DELETED DEMA1N (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 recherche
  • visible : l’EE a complété son inscription (photo + parcours pour l’année en cours) ; seuls les éclaireurs visible sont affichés aux lycéens
  • inactif : 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 ; isElasticVerified repasse à false pour désindexation

Champs savedData (JSON) :

  • stateOfMind : stateOfMind
  • activitesBacPro : activitesBacPro
  • currentClasseId : currentClasseId
  • savedParcoursLyceenData : Données de parcours lycéen sauvegardées
  • savedParcoursEclaireurData : Données de parcours éclaireur sauvegardées

Relations :

  • tags : Tags créés par l'utilisateur
  • parcoursLyceens : Parcours lycéen de l'utilisateur
  • parcoursEclaireurs : Parcours éclaireur de l'utilisateur
  • mvlsEclaireur : MVLS éclaireur de l'utilisateur (relation one-to-one — un utilisateur ne peut avoir qu'un seul MvlsEclaireur, voir entities/mvls.md)
  • mvlsLyceen : MVLS lycéen de l'utilisateur (relation one-to-one — un utilisateur ne peut avoir qu'un seul MvlsLyceen, voir entities/mvls.md)
  • userJwt : Informations d'authentification
  • comments : Commentaires postés par l'utilisateur
  • medias : Médias créés par l'utilisateur
  • chatChannels : Canaux de chat de l'utilisateur
  • userImpacts : 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éen
  • cron_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-expiry ajoute forgetPasswordExpiresAt. Elle ne modifie pas activated.
  • 1791200000000-activate-roles-requiring-activation passe activated à true pour 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ée
  • superieur : Supérieur

Relations :

  • parcoursLyceens : Parcours lycéens de cet établissement
  • parcoursEclaireurs : Parcours éclaireurs de cet établissement
  • formations : 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) : BUT
  • Brevet de Technicien Supérieur (BTS) : BTS
  • Certificat de Spécialisation (CS) : CS
  • Classe Préparatoire aux Grandes Ecoles (CPGE) : CPGE
  • Diplôme d'Etudes Universitaires Scientifiques et Techniques (DEUST) : DEUST
  • Ecole post-bac : École post-bac
  • Formation Complémentaire d'Initiative Locale (FCIL) : FCIL
  • Insertion : Insertion
  • Licence : Licence
  • Autre : 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 piste
  • avis_article_orientation : Avis sur un article d'orientation
  • avis_article_vie : Avis sur un article de vie étudiante
  • avis_reco_pistes : Avis sur les recommandations de pistes

Relations :

  • user : Utilisateur associé
  • piste : Piste associée (si applicable)
  • article : Article associé (si applicable)