corentin_wakdo/docs/merise/mcd.md
Imugiii b8cb3ef68d docs(merise): commit P1 conception v0.1 (dictionary, MCD, MCT, MLT, MLD) + UML
Baseline of the P1 conception work produced over sessions 5-7 (was
uncommitted in the working tree). 11-entity model, French naming.
Superseded next by the prod-like revision (English, ~16 entities) per
the 2026-06-04 decision session - this commit preserves the baseline
in history before that rewrite.
2026-06-04 10:19:25 +00:00

309 lines
15 KiB
Markdown

# Modele Conceptuel des Donnees (MCD) - Wakdo
**Phase Merise** : P1 - Conception, etape 2 (apres dictionnaire de donnees)
**Statut** : v0.1
**Date** : 2026-04-30
**Branche** : `feat/p1-conception`
---
## 1. Objet du document
Le MCD (Modele Conceptuel des Donnees) formalise les **entites** du domaine
Wakdo, leurs **associations** et les **cardinalites** qui regissent ces
associations. Il est la traduction normalisee du dictionnaire de donnees, et
sert de base au MLD (Modele Logique des Donnees) qui produira le schema
relationnel.
A la difference du dictionnaire (qui detaille les attributs et types), le MCD
focalise sur la structure relationnelle : combien de X pour un Y, est-ce
obligatoire, peut-il y avoir des relations sans participants ?
**Sources** :
- `docs/merise/dictionary.md` (entites + attributs identifies)
- `docs/PROJECT_CONTEXT.md` (regles metier : composition menu, parcours commande, RBAC)
- `docs/merise/_sources/` (donnees ecole : 9 categories + 53 produits + 13 menus)
---
## 2. Notation Merise utilisee
### Cardinalites au pied de l'association (style francais)
A chaque extremite d'une association, la cardinalite `(min, max)` precise
combien de fois une instance de l'entite participe a l'association.
```
ENTITE_A (min,max) ----[ ASSOCIATION ]---- (min,max) ENTITE_B
```
| Notation | Lecture | Exemple |
|---|---|---|
| `(0,1)` | Optionnel, au plus 1 | Un user a (0,1) avatar |
| `(1,1)` | Obligatoire, exactement 1 | Un produit appartient a (1,1) categorie |
| `(0,N)` | Optionnel, illimite | Une categorie regroupe (0,N) produits |
| `(1,N)` | Obligatoire au moins 1, illimite | Une commande contient (1,N) lignes |
Lecture francaise : "une instance de l'entite-source participe au moins MIN
fois et au plus MAX fois a l'association".
### Convention nommage des associations
Verbe a l'infinitif au sens metier, ex : `regroupe`, `compose`, `contient`,
`refere`, `a_pour_role`, `possede`.
Les associations qui portent des attributs (= relations N-N enrichies)
deviennent des **entites associatives** au MLD (table de jointure avec
colonnes propres).
---
## 3. Vue d'ensemble (diagramme global)
Diagramme entites-relations dessine dans draw.io, exporte en SVG. Les
sources `.drawio` editables sont dans `_diagrams/`. Cardinalites Merise
`(min,max)` notees directement sur les associations. Recapitulatif des
cardinalites en section 5.
![MCD - Diagramme global](_diagrams/mcd-global.svg)
*Source : [`_diagrams/mcd-global.drawio`](_diagrams/mcd-global.drawio)*
> **A regenerer** : le diagramme global doit etre mis a jour pour inclure l'entite `COMMANDE_EVENT` (11 entites au total) et l'attribut `source` sur `COMMANDE`. Le SVG actuel reflete l'etat anterieur a ces decisions.
### Lecture rapide
- Une `CATEGORIE` regroupe `(0,N)` `PRODUIT` ou `MENU` ; un `PRODUIT` ou un
`MENU` appartient a `(1,1)` categorie (chacun cote sa categorie de
rattachement).
- Un `MENU` est compose de `(1,N)` produits (un menu sans composition n'a pas
de sens metier) ; un `PRODUIT` peut faire partie de `(0,N)` menus
(independance).
- Une `COMMANDE` contient `(1,N)` `LIGNE_COMMANDE` (commande vide impossible) ;
une ligne appartient a `(1,1)` commande.
- Une `LIGNE_COMMANDE` refere `(0,1)` `PRODUIT` OU `(0,1)` `MENU` selon le
discriminateur `type_item` (polymorphisme).
- Une `COMMANDE` est journalisee par `(1,N)` `COMMANDE_EVENT` (au moins 1 event `CREATED`, append-only).
- Un `USER` declenche `(0,N)` `COMMANDE_EVENT` (NULL possible si event auto-kiosk).
- Un `USER` a `(1,1)` `ROLE` (un user sans role ne peut pas se connecter) ;
un `ROLE` peut etre porte par `(0,N)` users.
- Un `ROLE` possede `(0,N)` `PERMISSION` via `ROLE_PERMISSION` (matrice N-N).
---
## 4. Decomposition par sous-domaine
Le modele est segmente en 3 sous-domaines pour faciliter la lecture et
l'analyse :
1. **Catalogue** : produits, menus, categories, composition
2. **Commande** : commande, lignes, references polymorphiques
3. **RBAC** : users, roles, permissions, mapping
### 4.1 Sous-domaine Catalogue
![MCD - Catalogue](_diagrams/mcd-catalogue.svg)
*Source : [`_diagrams/mcd-catalogue.drawio`](_diagrams/mcd-catalogue.drawio)*
#### Justification des cardinalites
| Cote | Cardinalite | Justification |
|---|---|---|
| Categorie -> Produit | `(0,N)` cote Categorie | Une categorie peut etre creee a vide (ex : "petit dejeuner" ajoutee sans produit initial). Maximum illimite (au moins 53 produits dans la source actuelle, repartis sur 9 categories). |
| Categorie -> Produit | `(1,1)` cote Produit | Tout produit doit etre rattache a une categorie pour etre affiche sur la borne. Pas de produit "orphelin". |
| Categorie -> Menu | `(0,N)` cote Categorie | Toutes les categories sauf "menus" ont 0 menu. La categorie "menus" en a 13. |
| Categorie -> Menu | `(1,1)` cote Menu | Tout menu est rattache a la categorie "menus" (par construction du modele). Un menu sans categorie ne s'affiche pas sur la borne. |
| Menu -> MenuProduit | `(1,N)` cote Menu | Un menu doit avoir au moins 1 produit dans sa composition. Sans composition, le menu est invendable. |
| Produit -> MenuProduit | `(0,N)` cote Produit | Un produit peut exister independamment des menus (vente a la carte uniquement). Inversement, un produit peut entrer dans plusieurs menus differents (ex : frites moyennes presentes dans plusieurs combos). |
#### Note sur l'entite associative `MENU_PRODUIT`
`MENU_PRODUIT` est une entite associative : la relation N-N entre `MENU` et
`PRODUIT` porte deux attributs metier (`role` et `position`). Au MLD, elle
deviendra une table de jointure avec PK composite `(menu_id, produit_id)`.
### 4.2 Sous-domaine Commande
![MCD - Commande](_diagrams/mcd-commande.svg)
*Source : [`_diagrams/mcd-commande.drawio`](_diagrams/mcd-commande.drawio)*
> **A regenerer** : le diagramme `mcd-commande.drawio` doit etre mis a jour pour inclure l'entite `COMMANDE_EVENT` (cf. section 4.2.bis ci-dessous) et l'attribut `source` sur `COMMANDE`. Le SVG actuel reflete l'etat anterieur a ces decisions.
#### Justification des cardinalites
| Cote | Cardinalite | Justification |
|---|---|---|
| Commande -> LigneCommande | `(1,N)` cote Commande | Une commande sans aucune ligne n'a pas de sens metier. Au moment de la validation (passage de `pending_payment` a `paid`), au moins 1 ligne est presente. |
| Commande -> LigneCommande | `(1,1)` cote LigneCommande | Toute ligne appartient a exactement une commande. ON DELETE CASCADE (si commande supprimee, lignes aussi). |
| LigneCommande -> Produit | `(0,N)` cote Produit | Un produit peut etre commande des centaines de fois. Maximum non borne. |
| LigneCommande -> Produit | `(0,1)` cote LigneCommande | Selon `type_item` : si `'produit'` -> 1 produit reference ; si `'menu'` -> 0 (la colonne `produit_id` est NULL). |
| LigneCommande -> Menu | `(0,N)` cote Menu | Symetrique de Produit. |
| LigneCommande -> Menu | `(0,1)` cote LigneCommande | Selon `type_item` : si `'menu'` -> 1 menu reference ; si `'produit'` -> 0. |
| Commande -> CommandeEvent | `(1,N)` cote Commande | Toute commande a au moins 1 event (CREATED) ; en pratique 5-8 events sur tout son cycle de vie. |
| Commande -> CommandeEvent | `(1,1)` cote CommandeEvent | Chaque event appartient a exactement une commande. ON DELETE CASCADE. |
| User -> CommandeEvent | `(0,N)` cote User | Un equipier peut declencher 0 a N events (un nouveau user n'a encore rien fait). |
| User -> CommandeEvent | `(0,1)` cote CommandeEvent | NULL si event auto (kiosk paye via CB sans equipier) ou si le user a ete supprime (ON DELETE SET NULL preserve l'audit). |
#### Note sur le polymorphisme
La cardinalite `(0,1)` cote LigneCommande pour les deux associations
`refere_si_type_produit` et `refere_si_type_menu` reflete le polymorphisme :
**exactement une** des deux references est non-nulle, l'autre est nulle.
Cette regle d'exclusivite est a renforcer au MLD via une contrainte CHECK
SQL ou une regle applicative :
```sql
CHECK (
(type_item = 'produit' AND produit_id IS NOT NULL AND menu_id IS NULL)
OR (type_item = 'menu' AND menu_id IS NOT NULL AND produit_id IS NULL)
)
```
Voir `docs/notes/polymorphic-fk-snapshots.md` pour le detail du choix de
modelisation polymorphique.
#### 4.2.bis Journal d'audit `COMMANDE_EVENT` (event sourcing simplifie)
`COMMANDE_EVENT` est une entite append-only qui journalise chaque changement d'etat d'une commande, avec l'auteur de la transition (un `USER` ou NULL si auto). Pattern event sourcing simplifie (cf. note 10 du dictionnaire).
Trois proprietes invariantes :
1. **Append-only** : aucun UPDATE / DELETE applicatif sur `commande_event`. Garantie d'integrite de l'audit.
2. **Lien fort a la commande** : `ON DELETE CASCADE` cote `commande_id` (si la commande disparait, son journal aussi).
3. **Lien faible a l'user** : `ON DELETE SET NULL` cote `user_id` (si un equipier est supprime, les events restent avec `user_id = NULL` ; l'audit reste consultable, seule l'attribution individuelle est perdue).
La contrainte croisee `(source, mode_consommation)` introduite par l'attribut `source` sur `COMMANDE` (cf. dictionnaire note 8) est verifiee au MLT lors de la creation de la commande, pas au MCD.
### 4.3 Sous-domaine RBAC
![MCD - RBAC](_diagrams/mcd-rbac.svg)
*Source : [`_diagrams/mcd-rbac.drawio`](_diagrams/mcd-rbac.drawio)*
#### Justification des cardinalites
| Cote | Cardinalite | Justification |
|---|---|---|
| User -> Role | `(1,1)` cote User | Un user doit avoir un role pour acceder au back-office. Pas de connexion sans role. |
| User -> Role | `(0,N)` cote Role | Un role peut exister sans aucun user (ex : nouveau role cree dans l'UI admin avant d'etre assigne). |
| Role -> Permission (via ROLE_PERMISSION) | `(0,N)` cote Role | Un role peut avoir 0 permission (role "vide" ou "en construction") jusqu'a toutes les permissions (admin). |
| Role -> Permission (via ROLE_PERMISSION) | `(0,N)` cote Permission | Une permission peut etre assignee a 0 role (permission declaree mais pas encore distribuee) ou a plusieurs roles. |
#### Note sur le modele RBAC
Le RBAC retenu est **dynamique cote roles** (creables/modifiables via UI
admin) et **statique cote permissions** (declarees en migration, liees au
code applicatif). Voir `docs/notes/rbac-roles-permissions.md` pour le detail
du choix.
---
## 5. Recapitulatif global des cardinalites
| # | Association | Cote A | Cardinalite A | Cote B | Cardinalite B |
|---|---|---|---|---|---|
| 1 | regroupe (Categorie -> Produit) | Categorie | (0,N) | Produit | (1,1) |
| 2 | regroupe (Categorie -> Menu) | Categorie | (0,N) | Menu | (1,1) |
| 3 | compose (Menu <-> Produit via MenuProduit) | Menu | (1,N) | Produit | (0,N) |
| 4 | contient (Commande -> LigneCommande) | Commande | (1,N) | LigneCommande | (1,1) |
| 5 | refere_si_type_produit (LigneCommande -> Produit) | LigneCommande | (0,1) | Produit | (0,N) |
| 6 | refere_si_type_menu (LigneCommande -> Menu) | LigneCommande | (0,1) | Menu | (0,N) |
| 7 | journalise (Commande -> CommandeEvent) | Commande | (1,N) | CommandeEvent | (1,1) |
| 8 | declenche (User -> CommandeEvent) | User | (0,N) | CommandeEvent | (0,1) |
| 9 | a_pour_role (User -> Role) | User | (1,1) | Role | (0,N) |
| 10 | possede (Role <-> Permission via RolePermission) | Role | (0,N) | Permission | (0,N) |
---
## 6. Cross-validation avec le dictionnaire de donnees
Verification que chaque entite du dictionnaire est presente dans le MCD et
inversement.
| Entite dictionnaire (section 3) | Presente dans MCD ? | Sous-domaine |
|---|---|---|
| `categorie` (3.1) | Oui | Catalogue |
| `produit` (3.2) | Oui | Catalogue |
| `menu` (3.3) | Oui | Catalogue |
| `menu_produit` (3.4) | Oui (entite associative) | Catalogue |
| `commande` (3.5) | Oui | Commande |
| `ligne_commande` (3.6) | Oui | Commande |
| `commande_event` (3.7) | Oui (journal d'audit) | Commande |
| `user` (3.8) | Oui | RBAC |
| `role` (3.9) | Oui | RBAC |
| `permission` (3.10) | Oui | RBAC |
| `role_permission` (3.11) | Oui (entite associative) | RBAC |
Coherence : 100%. Aucune entite du dictionnaire n'est absente du MCD, aucune
entite du MCD n'est en plus du dictionnaire.
---
## 7. Decisions reportees au MLD
Le MCD reste au niveau conceptuel. Les decisions suivantes sont reportees au
MLD (modele logique des donnees, etape suivante) :
1. **Resolution des entites associatives en tables** : `MENU_PRODUIT` et
`ROLE_PERMISSION` deviendront des tables de jointure avec PK composite.
2. **Choix des PK techniques vs metier** : pour les entites principales, PK
technique `id INT UNSIGNED AUTO_INCREMENT`. Pour `commande`, garder
un identifiant metier `numero` UNIQUE en plus de l'id technique.
3. **Index techniques** : non discutes au MCD (couche logique). Au MLD :
index sur les FK, sur les colonnes `est_actif`/`est_disponible`, sur les
colonnes utilisees dans les `WHERE`/`ORDER BY` frequents (`created_at`,
`statut`).
4. **Contraintes CHECK SQL** : la regle d'exclusivite polymorphique sur
`LIGNE_COMMANDE` sera materialisee via CHECK en MariaDB 10.2+, ou via
trigger sur versions anteriures.
5. **Triggers / vues** : non identifies au MCD. A evaluer au MLD pour les
denormalisations utiles (vue `commande_avec_total` ?).
---
## 8. Coherence avec le MCT
Le MCT (Modele Conceptuel des Traitements) decrira les operations metier qui
manipulent ces entites :
- **Composer panier** (kiosk) : creation de COMMANDE statut `pending_payment` + insertion COMMANDE_EVENT `CREATED`
- **Valider payment** : transition COMMANDE statut `pending_payment` -> `paid` + insertion COMMANDE_EVENT `PAID`
- **Preparer commande** (cuisine) : transition `paid` -> `preparing` + insertion COMMANDE_EVENT `PREPARING_STARTED`
- **Marquer pret** : transition `preparing` -> `ready` + insertion COMMANDE_EVENT `READY`
- **Remettre client** : transition `ready` -> `delivered` + insertion COMMANDE_EVENT `DELIVERED`
- **Annuler** : transition vers `cancelled` (depuis tout statut sauf `delivered`) + insertion COMMANDE_EVENT `CANCELLED`
- **CRUD admin** : operations sur PRODUIT, MENU, CATEGORIE, USER, ROLE
Cross-validation MCD <-> MCT (mantra #34) : verifier au MCT que chaque
entite du MCD participe a au moins un traitement, et que chaque traitement
manipule des entites existantes du MCD.
Pre-validation rapide (intuitive, a re-valider au MCT) :
| Entite MCD | Au moins 1 traitement attendu ? |
|---|---|
| Categorie | Oui (CRUD admin) |
| Produit | Oui (CRUD admin + ajout panier) |
| Menu | Oui (CRUD admin + ajout panier) |
| MenuProduit | Oui (composition menu admin) |
| Commande | Oui (cycle de vie complet) |
| LigneCommande | Oui (creation panier) |
| CommandeEvent | Oui (insere a chaque transition de statut) |
| User | Oui (CRUD admin + login + declenchement events) |
| Role | Oui (CRUD admin + assignation) |
| Permission | Oui (consultation + assignation matrice) |
| RolePermission | Oui (matrice admin) |
---
## 9. A faire au prochain sprint (MCT)
- Lister exhaustivement les operations metier (acteurs, evenements
declencheurs, regles de declenchement)
- Modeliser les flux entre acteurs (client kiosk, equipier comptoir, equipier
cuisine, equipier drive, manager, admin)
- Identifier les synchronisations (ex : passage de `paid` a `preparing` peut
etre manuel cuisine ou automatique selon volume)
- Cross-valider MCD <-> MCT exhaustivement