Strapi v4 : Conception d’un Système d’Inscription pour les Profils Clients et Fournisseurs

Introduction

Notre use case concerne le développement d’une plateforme sur Strapi où les utilisateurs peuvent s’inscrire en tant que clients ou fournisseurs. Chaque utilisateur aura des informations spécifiques en fonction de son rôle : les clients fourniront des détails personnels tels que le nom et le prénom, adresse, le nom de la société si nécessaire etc…, tandis que les fournisseurs donneront des informations sur leur entreprise, comme le nom de la société, adresse, téléphone etc…. L’objectif est de créer une structure de données qui permet une gestion efficace des utilisateurs tout en différenciant les clients et les fournisseurs.

Prérequis

  1. Avoir une instance fonctionnelle de Strapi.

Exploration des Solutions Éventuelles

  1. Solution Unique avec des Champs Optionnels :
    • Créer un seul modèle User avec des champs optionnels pour les informations spécifiques des clients et fournisseurs.
    • Avantages : Structure simple.
    • Inconvénients : Possibilité de champs vides, complexité pour différencier les rôles.
  2. Solution avec Deux Modèles (Client et Fournisseur) :
    • Créer des modèles distincts pour les clients et les fournisseurs avec des relations “Has One Belongs To One” vers le modèle User.
    • Avantages : Clair et distinct, évite la redondance.
    • Inconvénients : Nécessite une gestion des relations.

Choix de la Solution et Motivations

La deuxième solution a été retenue, privilégiant des modèles distincts pour les clients et les fournisseurs, avec des liens “Has One Belongs To One” vers le modèle User. Voici les motivations derrière ce choix :

  1. Clarté et Distinction :
    • En ayant des modèles distincts pour les clients et les fournisseurs, chaque type d’utilisateur conserve une structure claire et distincte, facilitant la gestion et la compréhension.
  2. Éviter la Redondance :
    • En évitant de surcharger le modèle User avec des champs spécifiques à chaque type d’utilisateur, nous minimisons la redondance des données et préservons une structure plus légère et organisée.
  3. Gestion des Relations Facilitée :
    • Les relations “Has One Belongs To One” permettent d’établir des liens directs entre les utilisateurs, les clients et les fournisseurs, simplifiant la récupération des informations associées lors des opérations.
  4. Flexibilité pour l’Avenir :
    • En structurant notre base de données de cette manière, nous sommes mieux préparés pour des évolutions futures, comme l’ajout de nouveaux types d’utilisateurs ou de fonctionnalités spécifiques à chaque type.

En conclusion, la solution choisie offre une approche modulaire et claire pour gérer les différents types d’utilisateurs tout en minimisant la complexité et en préservant la flexibilité pour de futures évolutions de l’application.

Mise en place technique

Étape 1 : Conception technique

Notre système d’inscription utilise un modèle User central dans lequel chaque utilisateur possède un identifiant, un e-mail, un mot de passe, un rôle . Afin de faire une distinction entre les clients et les fournisseurs, nous avons introduit un champ d’énumération appelé “type”, prenant les valeurs “CLIENT” ou “FOURNISSEUR”.

Client :

  • Les clients disposent d’un modèle spécifique avec des champs tels que le prénom, le nom, adresse, téléphone etc…
  • Une relation est établie entre le modèle “Client” et le modèle “User” pour assurer une intégration transparente des données.

Fournisseur :

  • Les fournisseurs ont leur propre modèle avec des champs spécifiques comme le nom de la société, adresse, téléphone etc…
  • Une relation similaire est créée entre le modèle “Fournisseur” et le modèle “User”.

Étape 2 : Créer les content-types Client et fournisseur.

Dans cette étape, nous allons définir les modèles nécessaires pour les User, les clients et les fournisseurs, en établissant des relations entre eux. Strapi défini par défaut un content-type “User” pour la gestion de comptes utilisateurs. Pour l’implémentation de notre fonctionnalité, nous allons créer les modèles Fournisseur et Client.

  1. Création du modèle Fournisseur :
    • Accédez à l’interface d’administration Strapi (http://localhost:1337/admin).
    • Allez dans “Content-Types Builder” > “Create new collection type”.
    • Créez la collection “Fournisseur” avec un champ si après: companyName, adresse, telephone.
  2. Création du modèle Client :
    • Dans “Content-Types Builder”, créez une collection “Client” avec des champs spécifiques tels que firstName, lastName, telephone, etc.
    • Établissez une relation avec le modèle “User” pour représenter le compte utilisateur du client. Pour cela :
      • Ajoutez un champ de type “Relation” appelé user.
      • Sélectionnez le modèle “User” comme modèle de référence pour cette relation.
  3. Configurer les Relations :
    • Ajoutez un nouveau champ de type “Relation” appelé user.
    • Dans les paramètres de la relation, choisissez le modèle “User” comme modèle de référence.
    • Sélectionnez le type de relation comme “has one belongs to one” pour représenter le lien entre chaque client et un utilisateur.
  4. Répéter le Processus pour le Modèle Fournisseur :
    • Suivez les mêmes étapes pour le modèle “Fournisseur”, ajouter un champ de type “Relation” appelé user et le lier au modèle “User” en choisissant “has one belongs to one”.

Décision prise – Choix de la relation “Has One Belongs To One” :

La décision de choisir la relation “Has One Belongs To One” entre les modèles Client/Fournisseur et le modèle User découle de la nécessité de maintenir une distinction nette entre les clients et les fournisseurs tout en évitant de surcharger le modèle User avec des champs spécifiques à chaque profil.

3. Ajouter un champ de type Enumeration dans “User”

Dans cette phase, nous souhaitons améliorer la gestion des utilisateurs en introduisant un champ d’énumération appelé type. Ce champ aura deux valeurs possibles : “CLIENT” et “FOURNISSEUR”. L’objectif est de spécifier le profil de chaque utilisateur dès son inscription. Pour mettre en œuvre cette fonctionnalité, nous allons ajuster le processus d’enregistrement des utilisateurs en ajoutant ce champ d’énumération. Ainsi, cela facilitera la distinction entre les clients et les fournisseurs.

  1. Ajouter un Champ : Dans le modele User ajouter un champ de type Enumeration
  2. Nommer le Champ : Donnez un nom significatif à votre champ, par exemple “type” pour représenter le rôle de l’utilisateur.

Étape 3 : Gestion de l’inscription

Dans cette étape, nous allons configurer le processus d’insertion de données pour permettre à chaque utilisateur d’être enregistré en tant que client ou fournisseur en fonction du type choisi lors de son inscription. Pour ce faire, nous allons détailler la mise en œuvre de cette fonctionnalité dans Strapi, en expliquant comment ajouter un client ou un fournisseur lors de l’inscription d’un utilisateur à l’aide d’un hook personnalisé. Nous explorerons le cycle de vie de cette opération pour une compréhension approfondie du processus.

Ajout Simultané avec un Hook dans le Cycle de Vie :

Dans notre cas, nous voulons ajouter un client ou un fournisseur lors de la création d’un utilisateur. Pour cela, nous utiliserons un hooks personnalisé dans le cycle de vie de la création d’un utilisateur.

  1. Cycle de Vie dans Strapi :
    • Strapi utilise des lifecycles pour intercepter différentes étapes de vie des entités. Ces lifecycles peuvent être utilisés pour personnaliser le comportement à différentes étapes, comme la création, la mise à jour ou la suppression d’une entité.
  2. Emplacement du Hook :
    • Les hooks de lifecycles pour les utilisateurs peuvent être placés dans le dossier ./api/user-permissions/content-types/user/lifecycles.js du module User. Si cela ne fonctionne pas, vous pouvez les placer dans le fichier index.js à la racine du projet.

J’ai initialement tenté de définir ces hooks dans le fichier ./api/user-permissions/content-types/user/lifecycles.js, un emplacement qui aurait semblé plus intuitif pour gérer le cycle de vie des utilisateurs. Cependant, cette approche ne produisait pas les résultats escomptés.

Une explication potentielle pourrait être liée à des mises à jour ou à des changements de version dans le framework Strapi. Il est possible que, dans certaines versions spécifiques de Strapi, l’approche que j’ai essayée aurait pu fonctionner sans problème. Cependant, dans mon cas, les hooks n’ont été efficaces que lorsqu’ils étaient définis dans le fichier index.js.

code

  bootstrap({ strapi }) {
    strapi.db.lifecycles.subscribe({
      models: ['plugin::users-permissions.user'],
      async beforeCreate(event) {
        const { data } = event.params;
        const ctx = strapi.requestContext.get();
        const fournisseurCtx = ctx.request.body.fournisseur;
        const clientCtx = ctx.request.body.client;
        console.log('Données avant la vérification :', ctx.request.body);
  
        if (data.typeUser === "FOURNISSEUR") {
          
          if (!fournisseurCtx ||
              fournisseurCtx.companyName === "") {
           
            throw new Error(`Le champ "companyName" ne peut pas être vide pour le type d'utilisateur "${data.typeUser}".`);
          }
        } else if (data.typeUser === "CLIENT") {
          if (!clientCtx || 
               clientCtx.companyName === "") {
            
            throw new Error(`Le champ "companyName" ne peut pas être vide pour le type d'utilisateur "${data.typeUser}".`);
          }
        }
      },
  
      async afterCreate(event) {
        const { result } = event;
        const { id } = result;
        const ctx = strapi.requestContext.get();
        const clientCtx = ctx.request.body.client;
        const fournisseurCtx = ctx.request.body.fournisseur;
        const typeUserCtx = ctx.request.body.typeUser;
       
        if (typeUserCtx === "CLIENT") {
          await strapi.service("api::client.client").create({
            data: {
              firstName: clientCtx.firstName.toString(),
              lastName:  clientCtx.lastName.toString(),
              companyName: clientCtx.companyName.toString(),
              // ... (Ajoutez d'autres champs si nécessaire)
              user: [id],
            },
          });
        } else if (typeUserCtx === "FOURNISSEUR") {
          await strapi.service("api::fournisseur.fournisseur").create({
            data: {
              companyName: fournisseurCtx.companyName.toString(),
              phoneNumber: fournisseurCtx.phoneNumber.toString(),
              // ... (Ajoutez d'autres champs si nécessaire)
              user: [id],
            },
          });
        }
  
        console.log('Utilisateur créé après l\'inscription', result);
      },
    });
},
  1. beforeCreate Hook :
    • Le hook beforeCreate s’exécute avant la création d’un utilisateur.
    • Il vérifie le type d’utilisateur (FOURNISSEUR ou CLIENT).
    • Si le type est FOURNISSEUR, il vérifie que le champ companyName n’est pas vide dans les données de la requête.
    • Si le type est CLIENT, il effectue une vérification similaire pour le champ companyName.
  2. Gestion des Erreurs :
    • Si la vérification échoue (le champ est vide), une exception est levée, empêchant la création de l’utilisateur.
  3. afterCreate Hook :
    • Le hook afterCreate s’exécute après la création réussie d’un utilisateur.
    • Il récupère l’ID de l’utilisateur nouvellement créé à partir du résultat de l’événement.
    • En fonction du type d’utilisateur, il utilise le service approprié (api::client.client ou api::fournisseur.fournisseur) pour créer un enregistrement associé à l’utilisateur.
    • Les champs nécessaires sont extraits de la requête d’origine (ctx.request.body) et utilisés pour créer les enregistrements associés dans les modèles Client ou Fournisseur.
    • Les ID de l’utilisateur sont associés à ces enregistrements.
  4. Logs :
    • Des messages de log sont utilisés pour enregistrer des informations utiles, tels que les données avant la vérification et une confirmation après la création.

En résumé, ce code assure une validation préalable à la création d’utilisateurs en fonction de leur type, et après la création réussie, il crée des enregistrements associés dans d’autres modèles avec les données fournies. Cela permet de personnaliser le processus de création d’utilisateurs en fonction de différents scénarios définis par les types d’utilisateurs.

Mariama Nour
Mariama Nour
Développeuse web full-stack

Passionnée de programmation, je maîtrise les langages tels que PHP et JAVA, C++, tout en tout en étant très adaptative. Familiarisée avec divers frameworks tels que Laravel, Tailwind CSS, Spring Boot et React Native, j'ai acquis une solide expérience en travaillant sur des projets variés, qu'il s'agisse de développement Web et mobile, de création d'API, de conception d'applications monétiques pour TPE, ou encore de projets d'art numérique.

5 2 votes
Évaluation de l'article
guest
0 Commentaires
Commentaires en ligne
Afficher tous les commentaires

Ingénierie informatique (SSII)

Applize crée des logiciels métiers pour accompagner les entreprises dans la transition vers le zéro papier.


Avez-vous un projet en tête ? Discutons-en.