Conception complete (Phase 0) pour formation-hub Acadenice : - 19 docs Merise Agile + UML + GitOps + plans (tests/deploy/ops/api) cf docs/00-readme.md pour l'index complet - Stack Docker compose (Docmost + Baserow + Postgres + Redis + MinIO local FS) compose.yml + compose.staging.yml + compose.prod.yml - CI/CD GitHub Actions skeleton (ci, deploy-staging, deploy-prod) - Bridge service skeleton (Hono + TS + Biome + Vitest + zod + pino) - Templates GitHub : PR + 3 issue types + CODEOWNERS + dependabot.yml - Scripts ops : healthcheck, backup quotidien, smoke-test post-deploy - LICENSE AGPL-3.0 + SECURITY.md + CONTRIBUTING.md + CHANGELOG.md - Diagramme drawIO archi infra (XML importable dans diagrams.net) Decisions structurelles enregistrees : - Scope CFA + Agence avec entite PERSONNE pivot multi-roles (ADR-001) - Stack composite Docmost AGPL + Baserow MIT + bridge custom (ADR-001) - Path B : UX quasi-unified via Tiptap node-views custom (ADR-002) - Monorepo trunk-based development (ADR-003) - Postgres separe Docmost/Baserow (ADR-004) - Bridge stack Node 22 + Hono (ADR-005) - Repo neuf prefere a fork Docmost - Prod-like des le jour 1 (pas MVP)
7.9 KiB
MCD — Modele Conceptuel de Donnees
Vue conceptuelle des entites et relations. Scope B (CFA + Agence via PERSONNE pivot). Dictionnaire de donnees complet :
05-data-dictionary.md.
1. Vue d'ensemble
8 entites organisees en 3 zones :
| Zone | Entites |
|---|---|
| Pivot | PERSONNE |
| CFA | FORMATION, BLOC, MODULE + ATTRIBUTION (assoc.) |
| Agence | CLIENT, PROJET, TACHE + INTERVENTION (assoc.) |
PERSONNE est le pivot entre les deux activites : la meme personne peut avoir le role formateur (lie a ATTRIBUTION) et developpeur (lie a INTERVENTION). Sa capacite annuelle est splittee entre formation et agence.
2. Diagrammes entites-relations
Le modele complet a 9 entites — afficher tous les attributs sur un seul ER produit du spaghetti. On decompose en 5 vues : globale simplifiee + 3 zones detaillees + lien pedagogique.
2.1 Vue globale (simplifiee — entites et relations seules)
erDiagram
PERSONNE ||--o{ ATTRIBUTION : "formateur"
PERSONNE ||--o{ INTERVENTION : "developpeur"
FORMATION ||--o{ BLOC : ""
BLOC ||--o{ MODULE : ""
MODULE ||--o{ ATTRIBUTION : ""
CLIENT ||--o{ PROJET : ""
PROJET ||--o{ TACHE : ""
TACHE ||--o{ INTERVENTION : ""
PROJET }o--o| FORMATION : "pedagogique"
2.2 Zone CFA (formations + heures formateurs)
erDiagram
FORMATION ||--o{ BLOC : "1,N contient"
BLOC ||--o{ MODULE : "1,N comprend"
MODULE ||--o{ ATTRIBUTION : "0,N attribuee"
PERSONNE ||--o{ ATTRIBUTION : "0,N enseigne"
FORMATION {
int formation_id PK
string formation_nom UK
enum formation_filiere
decimal formation_heures_totales
enum formation_statut
date formation_date_debut
date formation_date_fin
}
BLOC {
int bloc_id PK
int bloc_formation_id FK
string bloc_nom
decimal bloc_heures_prevues
int bloc_ordre
}
MODULE {
int module_id PK
int module_bloc_id FK
string module_nom
decimal module_heures_prevues
enum module_statut
}
ATTRIBUTION {
int attribution_id PK
int attribution_module_id FK
int attribution_personne_id FK
decimal heures_attribuees
decimal heures_realisees
date date_debut
enum statut
}
PERSONNE {
int personne_id PK
string nom_prenom
decimal capacite_annuelle
}
2.3 Zone Agence (projets clients + heures devs)
erDiagram
CLIENT ||--o{ PROJET : "1,N a"
PROJET ||--o{ TACHE : "0,N comporte"
TACHE ||--o{ INTERVENTION : "0,N realisee"
PERSONNE ||--o{ INTERVENTION : "0,N realise"
CLIENT {
int client_id PK
string client_nom UK
string contact_email
enum statut
}
PROJET {
int projet_id PK
int projet_client_id FK
string projet_nom
enum type
decimal charge_heures
date date_debut
enum statut
}
TACHE {
int tache_id PK
int tache_projet_id FK
string titre
decimal charge_heures
enum priorite
enum statut
}
INTERVENTION {
int intervention_id PK
int intervention_tache_id FK
int intervention_personne_id FK
decimal heures
date intervention_date
enum statut
}
PERSONNE {
int personne_id PK
string nom_prenom
decimal capacite_annuelle
}
2.4 Zone Personne pivot (capacite + roles)
erDiagram
PERSONNE ||--o{ ATTRIBUTION : "role formateur"
PERSONNE ||--o{ INTERVENTION : "role developpeur"
PERSONNE {
int personne_id PK
string personne_nom
string personne_prenom
string personne_email UK
decimal capacite_annuelle
decimal split_formation_pct
decimal split_agence_pct
string roles "multi-select"
decimal heures_attribuees_formation "rollup"
decimal heures_attribuees_agence "rollup"
decimal heures_restantes_total "formula"
enum statut
}
ATTRIBUTION {
int attribution_id PK
int attribution_module_id FK
int attribution_personne_id FK
decimal heures_attribuees
}
INTERVENTION {
int intervention_id PK
int intervention_tache_id FK
int intervention_personne_id FK
decimal heures
}
2.5 Lien projet pedagogique (cross CFA-Agence)
erDiagram
PROJET }o--o| FORMATION : "0,1 projet pedagogique"
PROJET {
int projet_id PK
int projet_formation_id FK "nullable"
string projet_nom
}
FORMATION {
int formation_id PK
string formation_nom
}
Notation : ce lien est optionnel cote PROJET (un projet peut etre purement client). Cote FORMATION, plusieurs projets peuvent etre lies a une formation pedagogique.
3. Cardinalites detaillees
| Relation | Source | Cardinalite | Cible | Cardinalite | Sens metier |
|---|---|---|---|---|---|
| CONTIENT (CFA) | FORMATION | (1,N) | BLOC | (1,1) | une formation comprend des blocs RNCP |
| COMPREND (CFA) | BLOC | (1,N) | MODULE | (1,1) | un bloc se decompose en modules |
| ATTRIBUTION (CFA) | MODULE | (0,N) | PERSONNE | (0,N) | un module est dispense par 0-N formateurs |
| EMPLOIE (Agence) | CLIENT | (1,N) | PROJET | (1,1) | un client peut avoir des projets |
| COMPORTE (Agence) | PROJET | (0,N) | TACHE | (1,1) | un projet est decoupe en taches |
| INTERVENTION (Agence) | TACHE | (0,N) | PERSONNE | (0,N) | un dev peut intervenir sur 0-N taches |
| PROJET_PEDAGOGIQUE | PROJET | (0,1) | FORMATION | (0,N) | un projet client peut servir de support pedagogique a une formation |
4. Calculs (rollups + formulas) cles
PERSONNE.heures_attribuees_formation = SUM(ATTRIBUTION.heures_attribuees)
WHERE attribution_personne_id = personne_id
AND attribution_statut != 'annule'
PERSONNE.heures_attribuees_agence = SUM(INTERVENTION.heures)
WHERE intervention_personne_id = personne_id
AND intervention_statut != 'annule'
PERSONNE.heures_restantes_total = capacite_annuelle
- heures_attribuees_formation
- heures_attribuees_agence
PROJET.heures_realisees = SUM(TACHE.heures_realisees) WHERE tache_projet_id = projet_id
TACHE.heures_realisees = SUM(INTERVENTION.heures) WHERE intervention_tache_id = tache_id
(rollups CFA inchanges depuis version precedente — voir Data Dictionary)
5. Regles de gestion (extension)
- RG-PERSONNE-01 :
personne_split_formation_pct + personne_split_agence_pct = 100(CHECK constraint) - RG-PERSONNE-02 : Une attribution ne peut etre creee que si la personne a
formateurdans ses roles. - RG-PERSONNE-03 : Une intervention ne peut etre creee que si la personne a
developpeurdans ses roles. - RG-PERSONNE-04 :
heures_restantes_total >= 0est un warning UI, pas un blocage (depassement possible avec justification).
(RG CFA conserves : voir version precedente du MCD pour RG-FORMATION, RG-BLOC, RG-MODULE)
6. Questions ouvertes (a valider metier)
- Le split formation/agence est-il fixe par personne ou variable par periode (ex: trimestre 1 a 70/30, trimestre 2 a 50/50) ?
- Faut-il modeliser une notion de session (un module enseigne plusieurs fois a des promotions differentes) ?
- Faut-il une notion de promotion ou de classe dans le CFA ?
- Pour les projets pedagogiques (lien PROJET ↔ FORMATION), comment tracer les etudiants impliques ? (Si on ne modelise pas l'etudiant, on ne peut pas formellement le lier au projet — a discuter.)
- Workflow d'approbation des heures realisees (admin valide avant facturation ou paie) ?