MVLS — Intégration RabbitMQ

Retour : vue d'ensemble MVLS.

Intégration RabbitMQ

Types de messages

MVLS utilise plusieurs types de messages RabbitMQ :

1. Messages utilisateurs

  • USER_CREATED : Création d'un jeune ou bénévole MVLS
  • USER_UPDATED : Mise à jour d'un jeune ou bénévole MVLS
  • USER_DELETED : Suppression d'un jeune ou bénévole MVLS

2. Messages binômes

  • BINOME_CREATED : Création d'un binôme MVLS
  • BINOME_UPDATED : Mise à jour d'un binôme MVLS (changement de statut/état)

Format des messages

Structure générale

interface IMvlsRabbitMQMessage {
  header: {
    name: string; // "USER_CREATED", "USER_UPDATED", "USER_DELETED", "BINOME_CREATED", "BINOME_UPDATED"
    model: string; // "USER" ou "BINOME"
    event: string; // "CREATED", "UPDATED", "DELETED"
    date: string; // Date ISO 8601
    requestId: string; // Identifiant unique de la requête
    uniqid: string; // Identifiant unique du message
    VERSION: string; // "1.0"
    producer: string; // "dema1n"
  };
  body:
    | IFilterLyceenDataForMvlsResult
    | IFilterEclaireurDataForMvlsResult
    | IUserDeletedDataForMvlsResult
    | IBinomeDataForMvlsResult;
}

Message USER_CREATED / USER_UPDATED (Lycéen)

{
  "header": {
    "name": "USER_CREATED",
    "model": "USER",
    "event": "CREATED",
    "date": "2025-12-12T10:00:00.000Z",
    "requestId": "abc123",
    "uniqid": "xyz789",
    "VERSION": "1.0",
    "producer": "dema1n"
  },
  "body": {
    "charte": true,
    "notification": true,
    "newEmail": null,
    "user": {
      "gender": "M",
      "birthdate": "2007-05-15",
      "firstname": "Jean",
      "lastname": "Dupont",
      "phoneNumber": "+33612345678",
      "roles": ["lyceen"],
      "userJwt": {
        "username": "jean.dupont@example.com",
        "ssoId": "sso-123",
        "activationToken": "token-abc"
      },
      "mvlsLyceens": [
        {
          "createdAt": "2025-12-01T10:00:00.000Z",
          "mentor_sexe": "M",
          "etudesSup": "totaly",
          "travailEfficace": "kinda",
          "preparationSup": "yes",
          "nomClasse": "Terminale S",
          "domaines": ["Sciences", "Technologie"],
          "formations": ["Bac+3", "Bac+5"],
          "communication": ["email", "phone"],
          "statut": "EN_ATTENTE",
          "state": "ACTIF"
        }
      ],
      "parcoursLyceens": [
        {
          "createdAt": "2025-12-01T10:00:00.000Z",
          "filiere": "Scientifique",
          "isBoursierSecondaire": "OUI",
          "etablissement": {
            "departmentCode": "75",
            "nom": "Lycée Victor Hugo"
          }
        }
      ]
    }
  }
}

Champ newEmail (optionnel) :

  • Type : string | null
  • Emplacement : Au niveau du body (racine du body)
  • Description : Nouvel email de l'utilisateur si différent de user.userJwt.username. Si présent et différent de username, l'email de l'utilisateur sera mis à jour dans DEMA1N avec le préfixe mvls_ (ex: mvls_nouvel.email@example.com).
  • Exemple avec changement d'email :
{
  "body": {
    "charte": true,
    "notification": true,
    "newEmail": "nouvel.email@example.com",
    "user": {
      "userJwt": {
        "username": "ancien.email@example.com"
      }
    }
  }
}

Message USER_DELETED

{
  "header": {
    "name": "USER_DELETED",
    "model": "USER",
    "event": "DELETED",
    "date": "2025-12-12T10:00:00.000Z",
    "requestId": "abc123",
    "uniqid": "xyz789",
    "VERSION": "1.0",
    "producer": "dema1n"
  },
  "body": {
    "email": "jean.dupont@example.com"
  }
}

Message BINOME_CREATED / BINOME_UPDATED

{
  "header": {
    "name": "BINOME_CREATED",
    "model": "BINOME",
    "event": "CREATED",
    "date": "2025-12-12T10:00:00.000Z",
    "requestId": "abc123",
    "uniqid": "xyz789",
    "VERSION": "1.0",
    "producer": "dema1n"
  },
  "body": {
    "binome_id": "123",
    "jeune_id": "456",
    "benevole_id": "789",
    "jeune_email": "jean.dupont@example.com",
    "benevole_email": "marie.martin@example.com",
    "status": "EN_ATTENTE",
    "state": "ACTIF",
    "creationDate": "2025-12-12T10:00:00.000Z",
    "buildDate": null,
    "statusUpdateDate": "2025-12-12T10:00:00.000Z"
  }
}

Routing Key

Tous les messages MVLS utilisent le même routing key : user___mvls

Quand les messages sont envoyés

Messages utilisateurs

  • USER_CREATED : Lors de la création d'un jeune ou bénévole MVLS
  • USER_UPDATED :
  • Lors de la mise à jour d'un jeune MVLS via JeuneService.updateAdmin()
  • Lors de la mise à jour d'un bénévole MVLS via BenevolesService.updateAdmin()
  • USER_DELETED :
  • Lors de la suppression d'un jeune MVLS via JeuneService.deleteJeune()
  • Lors de la suppression d'un bénévole MVLS via BenevolesService.deleteBenevole()

Messages binômes

  • BINOME_CREATED : Lors de la création d'un binôme MVLS via BinomeService.createBinome()
  • BINOME_UPDATED : Lors de la mise à jour d'un binôme MVLS (changement de statut ou d'état)

Messages suivis

  • SUIVI_CREATED : Lors de la création d'un suivi MVLS (checkpoint) via SuivistatusService.createSuivistatus()
  • SUIVI_UPDATED : Lors de la mise à jour d'un suivi MVLS via SuivistatusService.changeSuivistatus()

Format du message SUIVI_CREATED / SUIVI_UPDATED :

{
  "header": {
    "name": "SUIVI_CREATED",
    "model": "SUIVI",
    "event": "CREATED",
    "date": "2025-12-12T10:00:00.000Z",
    "requestId": "abc123",
    "uniqid": "xyz789",
    "VERSION": "1.0",
    "producer": "dema1n"
  },
  "body": {
    "suivi": {
      "suivi_id": "123",
      "binome_id": "456",
      "step_id": "789",
      "day_step": 5,
      "status": "EN_ATTENTE",
      "status_jeune": "EN_ATTENTE",
      "status_benevole": "EN_ATTENTE",
      "creation_date": "2025-12-12T10:00:00.000Z",
      "status_update_date": "2025-12-12T10:00:00.000Z"
    }
  }
}

Réponse d'Inspire (lien dans l'email de checkpoint)

Les emails Brevo de checkpoint reçoivent {{ params.contactok }} (RAS, actif = '1') et {{ params.nocontact }} (problème, actif = '0'), construits dans MessagesService (binomes/services/messages.service.ts) :

{INSPIRE_BASE_URL}/mentorat/suivi/:token/:contactStatus/:suiviId/:type avec contactStatus = jeune | benevole, type = contactok | nocontact et token = md5(binomeId + '/suivi/' + suiviId + '/' + contactStatus + '/' + type).

Inspire répond par un message SUIVI_UPDATE_FROM_INSPIRE (exchange dema1n, routing key user___mvls, body.suivi_update). Champs : ISuiviUpdateFromInspire dans back/src/mvls/mvls.interfaces.ts ; traitement : MvlsService (ignore les suivis inconnus ou non MVLS, sans erreur renvoyée). DEMA1N notifie ensuite SUIVI_UPDATED.

Réception des messages

Le service MVLS écoute les messages entrants via RabbitMQ :

@RabbitRPC({
  exchange: 'dema1n',
  queue: 'Dema1n_mvls',
  routingKey: 'user___mvls'
})
public async pubSubHandler(msg: IMvlsRabbitMQMessage) {
  // Traitement des messages reçus
}

Gestion du champ newEmail dans USER_UPDATED et USER_CREATED

Lors de la réception d'un message USER_UPDATED ou USER_CREATED, le champ newEmail peut être présent au niveau du body pour indiquer un changement d'email :

  • Si newEmail est présent et différent de user.userJwt.username :
  • L'utilisateur est recherché par son ancien email (avec préfixe mvls_) : mvls_ + user.userJwt.username
  • L'email de l'utilisateur est mis à jour avec le nouvel email (avec préfixe mvls_) : mvls_ + newEmail
  • Les autres champs de l'utilisateur sont également mis à jour selon les données du message

  • Si newEmail est null ou identique à username :

  • Aucune mise à jour de l'email n'est effectuée
  • Seuls les autres champs sont mis à jour

Exemple de traitement :

// Message reçu avec newEmail différent de username
{
  "body": {
    "newEmail": "nouvel.email@example.com",
    "user": {
      "userJwt": {
        "username": "ancien.email@example.com"
      }
    }
  }
}

// Comportement :
// 1. Recherche de l'utilisateur : findByEmailMvls('mvls_ancien.email@example.com')
// 2. Mise à jour de l'email : user.email = 'mvls_nouvel.email@example.com'
// 3. Mise à jour des autres champs (firstName, lastName, etc.)