Modélisation de base de données : Le cas Langlois #
Introduction #
La modélisation de bases de données est une étape cruciale dans la conception d’un système d’information. Elle permet de structurer les données de manière cohérente et efficace avant leur implémentation physique. Dans cet article, nous allons étudier le cas Langlois, une entreprise de distribution d’équipements spécialisés, et concevoir un modèle de base de données complet pour gérer son catalogue et ses demandes de devis.
Contexte : Le cas Langlois #
Présentation de l’entreprise #
Langlois est une société historique basée dans la périphérie de Bordeaux. Son activité principale est la fabrication et la gestion d’inventaires d’équipements spécialisés :
- Équipements électroniques
- Électroménagers
- Matériaux de construction
Caractéristiques du catalogue #
400 000 articles sont disponibles dans le catalogue. Déclinaisons infinies possibles : couleur, hauteur, longueur, largeur, matériau, etc. Chaque déclinaison influence le prix de base via un pourcentage.
Objectifs du projet #
Dans le cadre de son développement international, Langlois souhaite :
- Créer une interface UI multilingue
- Permettre aux clients de consulter le catalogue
- Générer des demandes de devis personnalisées
- Gérer les restrictions géographiques sur certains produits
Exigences Fonctionnelles #
Le système doit permettre de répondre aux requêtes suivantes :
Requêtes Métier :
- Lister les produits les plus demandés (en descendant de catalogue)
- Lister les demandes de devis effectuées avec calcul des prix selon les déclinaisons
- Lister les produits qui n’ont pas de déclinaisons
- Lister les produits les plus demandés (en nombre de devis)
- Extraire le nombre de demandes de cotations sur l’année 2024
- Connaître le nombre de fois qu’un produit a été demandé en 2025
Modèle Conceptuel de Données (MCD) #
erDiagram
TYPE_DECH ||--o{ PRODUIT : "décrit"
TYPE_DECH ||--o{ DECH_PRODUIT : "définit"
FAMILLE ||--o{ FAMILLE : "parent/enfant"
FAMILLE ||--o{ PRODUIT : "contient"
PRODUIT ||--o{ DECH_PRODUIT : "a des déclinaisons"
PRODUIT }o--o{ DEVIS : "DEVIS_PRODUIT"
PRODUIT }o--o{ PAYS : "PAYS_BANNI"
CLIENT ||--o{ DEVIS : "demande"
CLIENT }o--|| PAYS : "réside"
PAYS ||--o{ PAYS_BANNI : "interdit"
DEVIS ||--|{ DEVIS_PRODUIT : "contient"
Entités Principales #
TYPE_DECH - Type de Déclinaison #
Définit les types de variations possibles pour les produits.
Attributs :
id_type_dech(PK) : Identifiant uniquelibelle_dech: Nom du type (hauteur, couleur, voltage, etc.)
Exemples :
| id_type_dech | libelle_dech |
|---|---|
| 1 | hauteur |
| 22 | couleur |
| 115 | voltage |
Cardinalité :
- Un TYPE_DECH peut s’appliquer à plusieurs PRODUIT (1,n)
- Un TYPE_DECH peut avoir plusieurs DECH_PRODUIT (1,n)
PRODUIT - Catalogue Produits #
Le cœur du système : référence chaque article disponible.
Attributs :
id_produit(PK) : Identifiant uniquelibelle_produit: Nom commercial du produitref_produit: Référence unique (ex: “00001”)description_produit: Description détailléeprix_base_produit: Prix de base en eurosqte_produit: Quantité en stockid_type_dech(FK) : Type de déclinaison applicableid_famille(FK) : Catégorie du produit
Exemple :
| id_produit | libelle_produit | ref_produit | prix_base_produit | qte_produit |
|---|---|---|---|---|
| 1 | Carton standard | 00001 | 12.50 | 1500 |
| 2 | Laptop Pro 15" | 10002 | 1299.00 | 75 |
Cardinalité :
- Un PRODUIT appartient à une FAMILLE (1,1)
- Un PRODUIT a un TYPE_DECH ou aucun (0,1)
- Un PRODUIT peut avoir plusieurs DECH_PRODUIT (0,n)
DECH_PRODUIT - Déclinaisons de Produits #
Cette table stocke les valeurs spécifiques des déclinaisons pour chaque produit.
Attributs :
dech_produit(PK) : Identifiantid_dech(FK) : Type de déclinaison (référence TYPE_DECH)id_produit(FK) : Produit concernévaleur: Valeur numérique (120 pour 120cm)mesure: Unité de mesure (cm, kg, volts)pct_dech: Pourcentage de modification du prix
Exemple :
| dech_produit | id_dech | id_produit | valeur | mesure | pct_dech |
|---|---|---|---|---|---|
| 1 | 1 (hauteur) | 1 | 50 | cm | 15.00 |
| 2 | 2 (longueur) | 1 | 80 | cm | 5.00 |
Formule de calcul du prix final :
Prix final = Prix de base × (1 + pct_dech₁/100) × (1 + pct_dech₂/100) × ...
Exemple concret :
- Prix de base : 100 €
- Déclinaison 1 (hauteur 120cm) : +15%
- Déclinaison 2 (largeur spéciale) : +5%
- Prix final = 100 × 1.15 × 1.05 = 120.75 €
Cardinalité :
- Une DECH_PRODUIT appartient à un PRODUIT (1,1)
- Une DECH_PRODUIT référence un TYPE_DECH (1,1)
FAMILLE - Hiérarchie de Catégories #
Cette table contient les informations de la hiérarchie du catalogue (arbre de catégories).
Attributs :
id_famille(PK) : Identifiantlibelle_famille: Nom de la catégoriedescription_famille: Descriptionid_parent(FK) : Référence vers la famille parent (auto-référence)
Structure hiérarchique :
mindmap
root((Catégories))
"Équipements — id 1 / parent NULL"
"Électronique — id 3 / parent 1"
"Smartphones — id 8 / parent 3"
"Ordinateurs — id 9 / parent 3"
"Électroménager — id 4 / parent 1"
"Cuisine — id 10 / parent 4"
"Quincaillerie — id 5 / parent 1"
"Matériaux — id 2 / parent NULL"
"Emballage — id 6 / parent 2"
"Cartons — id 11 / parent 6"
"Construction — id 7 / parent 2"
"Bois — id 12 / parent 7"
Cardinalité :
- Une FAMILLE peut avoir une famille parent (0,1)
- Une FAMILLE peut avoir plusieurs familles enfants (0,n)
- Une FAMILLE contient plusieurs PRODUIT (0,n)
L’auto-référence permet de créer une hiérarchie de profondeur infinie.
DEVIS - Demandes de Devis #
Cette table enregistre chaque demande de cotation d’un client.
Attributs :
- id_devis (PK) : Identifiant unique
- ref_devis : Référence externe (ex: “QR-2025-001”)
- date_devis : Date de création
- montant_devis : Montant total calculé
- id_client (FK) : Client demandeur
Cardinalité :
- Un DEVIS est créé par un CLIENT (1,1)
- Un DEVIS contient plusieurs PRODUIT via DEVIS_PRODUIT (1,n)
DEVIS_PRODUIT - Produits dans un Devis #
Cette table est une liaison entre DEVIS et PRODUIT (relation N:N).
Attributs :
- id_devis (PK, FK) : Devis concerné
- id_produit (PK, FK) : Produit demandé
- qte_produit : Quantité commandée
Cardinalité :
- Clé primaire composite : (id_devis, id_produit)
- Permet à un devis d’avoir plusieurs produits
- Permet à un produit d’apparaître dans plusieurs devis
CLIENT - Informations Clients #
Cette table stocke les données des demandeurs de devis.
Attributs :
- id_client (PK) : Identifiant unique
- nom_client : Nom de famille
- prenom_client : Prénom (optionnel)
- mobile_client : Numéro de téléphone
- id_pays (FK) : Pays de résidence
Cardinalité :
- Un CLIENT réside dans un PAYS (1,1)
- Un CLIENT peut créer plusieurs DEVIS (0,n)
PAYS - Pays et Zones Géographiques #
Cette table contient les référentiels des pays pour géolocalisation et restrictions.
Attributs :
- id_pays (PK) : Identifiant
- nom_pays : Nom du pays
- power_supply : Voltage standard (220V, 110V, 100V)
Les produits électriques sont souvent incompatibles selon les pays (transformateur nécessaire).
Cardinalité :
- Un PAYS peut avoir plusieurs CLIENT (0,n)
- Un PAYS peut bannir plusieurs PRODUIT via PAYS_BANNI (0,n)
PAYS_BANNI - Restrictions Géographiques #
Cette table est une liaison entre PRODUIT et PAYS pour gérer les interdictions de vente.
Attributs :
- id_produit (PK, FK) : Produit concerné
- id_pays (PK, FK) : Pays où le produit est interdit
C’est la zone géographique qui est bannie, non le client et son pays d’appartenance. Cela signifie :
Un produit peut être interdit à la vente dans certains pays Un client français peut quand même commander si le produit est livré ailleurs La restriction porte sur la destination de livraison, pas sur la nationalité du client
Cardinalité :
- Relation N:N entre PRODUIT et PAYS
- Un produit peut être banni dans plusieurs pays
- Un pays peut bannir plusieurs produits
Diagramme Entité-Association Détaillé #
erDiagram
TYPE_DECH {
int id_type_dech PK
string libelle_dech
}
PRODUIT {
int id_produit PK
string libelle_produit
string ref_produit UK
text description_produit
decimal prix_base_produit
int qte_produit
int id_type_dech FK
int id_famille FK
}
DECH_PRODUIT {
int dech_produit PK
int id_dech FK
int id_produit FK
decimal valeur
string mesure
decimal pct_dech
}
FAMILLE {
int id_famille PK
string libelle_famille
text description_famille
int id_parent FK
}
DEVIS {
int id_devis PK
string ref_devis UK
date date_devis
decimal montant_devis
int id_client FK
}
DEVIS_PRODUIT {
int id_devis PK_FK
int id_produit PK_FK
int qte_produit
}
CLIENT {
int id_client PK
string nom_client
string prenom_client
string mobile_client
int id_pays FK
}
PAYS {
int id_pays PK
string nom_pays UK
string power_supply
}
PAYS_BANNI {
int id_produit PK_FK
int id_pays PK_FK
}
TYPE_DECH ||--o{ PRODUIT : "DECRIT_PRODUIT (0,1)-(1,n)"
TYPE_DECH ||--o{ DECH_PRODUIT : "DEFINIT (1,1)-(0,n)"
FAMILLE ||--o{ FAMILLE : "PARENT_ENFANT (0,1)-(0,n)"
FAMILLE ||--o{ PRODUIT : "APPARTENIR (1,1)-(0,n)"
PRODUIT ||--o{ DECH_PRODUIT : "A_DECLINAISON (1,1)-(0,n)"
PRODUIT ||--o{ DEVIS_PRODUIT : "(1,1)-(0,n)"
PRODUIT ||--o{ PAYS_BANNI : "(1,1)-(0,n)"
DEVIS ||--|{ DEVIS_PRODUIT : "CONTIENT (1,1)-(1,n)"
CLIENT ||--o{ DEVIS : "DEMANDE (1,1)-(0,n)"
CLIENT }o--|| PAYS : "RESIDE (1,1)-(0,n)"
PAYS ||--o{ PAYS_BANNI : "INTERDIT (1,1)-(0,n)"
Exemples :
- PRODUIT (1,1) –> (0,n) FAMILLE : Un produit appartient à exactement une famille, une famille peut avoir zéro ou plusieurs produits
- DEVIS (1,1) –> (1,n) DEVIS_PRODUIT : Un devis contient au moins un produit