# UML Class Diagram > Vue orientee objet du modele. Scope B (CFA + Agence + Personne pivot). > Apporte les **methodes** que le MCD ne montre pas. Pont entre modele de donnees et code du bridge service Phase 2. ## 1. Pourquoi un class diagram en plus du MCD Le MCD montre les **donnees** (entites + attributs + relations). Le class diagram montre : - Les **methodes** sur chaque classe - La **visibilite** (public/private/protected) - Les **types de relations OO** (composition, agregation, association) - Les patterns applicables ## 2. Diagrammes par zone Splitte en 3 sous-vues : CFA, Agence, Personne pivot. Plus un diagramme global simplifie pour la vue d'ensemble. ### 2.1 Vue globale (relations seules) ```mermaid classDiagram Personne -- Attribution : "role formateur" Personne -- Intervention : "role developpeur" Formation *-- Bloc Bloc *-- Module Module -- Attribution Client -- Projet Projet *-- Tache Tache -- Intervention Projet -- Formation : "projet pedagogique" ``` ### 2.2 Zone CFA — classes detaillees ```mermaid classDiagram class Formation { +int id +string nom +Filiere filiere +decimal heuresTotales -decimal heuresAttribuees$ +Statut statut +activer() void +archiver() void +ajouterBloc(Bloc) void +heuresRestantes() decimal +rapportPDF() Buffer } class Bloc { +int id +string nom +decimal heuresPrevues -decimal heuresAttribuees$ +ajouterModule(Module) void +heuresRestantes() decimal } class Module { +int id +string nom +decimal heuresPrevues -decimal heuresAttribuees$ -decimal heuresRealisees$ +Statut statut +creerAttribution(Personne, decimal, Date, Date) Attribution +annuler() void +cloturer() void } class Attribution { +int id +decimal heuresAttribuees +decimal heuresRealisees +Statut statut +demarrer() void +saisirHeuresRealisees(decimal) void +cloturer() void +annuler(string) void } Formation "1" *-- "1..*" Bloc : composition Bloc "1" *-- "1..*" Module : composition Module "1" -- "0..*" Attribution : association ``` ### 2.3 Zone Agence — classes detaillees ```mermaid classDiagram class Client { +int id +string nom +string contactPrincipal +Email contactEmail +Statut statut +creerProjet(string) Projet +archiver() void } class Projet { +int id +string nom +Type type +decimal chargeHeures -decimal heuresRealisees$ +Statut statut +ajouterTache(string, decimal) Tache +lierFormationPedagogique(Formation) void +livrer() void +cloturer() void +rapportPDF() Buffer } class Tache { +int id +string titre +decimal chargeHeures -decimal heuresRealisees$ +Priorite priorite +Statut statut +creerIntervention(Personne, decimal, Date) Intervention +marquerInProgress() void +marquerReview() void +marquerDone() void } class Intervention { +int id +decimal heures +Date date +Statut statut +annuler(string) void } Client "1" -- "1..*" Projet : association Projet "1" *-- "0..*" Tache : composition Tache "1" -- "0..*" Intervention : association ``` ### 2.4 Zone Personne pivot — classe + roles ```mermaid classDiagram class Personne { +int id +string nom +string prenom +Email email +decimal capaciteAnnuelle +decimal splitFormationPct +decimal splitAgencePct +Set~Role~ roles +Statut statut -decimal heuresAttribueesFormation$ -decimal heuresAttribueesAgence$ +heuresRestantesFormation() decimal +heuresRestantesAgence() decimal +heuresRestantesTotal() decimal +ajouterRole(Role) void +retirerRole(Role) void +activer() void +inactiver() void +rapportPDF() Buffer } class Attribution { +int id +decimal heuresAttribuees +Statut statut } class Intervention { +int id +decimal heures +Statut statut } Personne "1" -- "0..*" Attribution : "role formateur" Personne "1" -- "0..*" Intervention : "role developpeur" ``` ### 2.5 Lien pedagogique cross-zone ```mermaid classDiagram class Projet { +int id +string nom +lierFormationPedagogique(Formation) void } class Formation { +int id +string nom } Projet "0..*" -- "0..1" Formation : "projet pedagogique" ``` **Notation** : - `+` public, `-` private, `#` protected - `$` champ derive/calcule (rollup ou formula, pas stocke directement) - `*--` composition (cycle de vie partage) - `--` association simple ## 3. Methodes detaillees — Personne | Methode | Signature | Description | |---------|-----------|-------------| | `heuresRestantesFormation()` | `decimal` | `(capacite * split_formation_pct/100) - heures_attribuees_formation` | | `heuresRestantesAgence()` | `decimal` | `(capacite * split_agence_pct/100) - heures_attribuees_agence` | | `heuresRestantesTotal()` | `decimal` | `capacite - heures_attribuees_formation - heures_attribuees_agence` | | `ajouterRole(role)` | `Role → void` | Ajoute role aux roles existants. Idempotent. | | `retirerRole(role)` | `Role → void` | Retire role. Verifie qu'aucune attribution/intervention active n'utilise ce role. | | `activer()` | `void` | Statut → actif | | `inactiver()` | `void` | Statut → inactif. Bloque nouvelles assignations. | ## 4. Methodes detaillees — Module / Tache ### Module.creerAttribution(personne, heures, dateDebut, dateFin) Verifications : - `personne.roles.contains(Role.formateur)` — sinon throw - `RG-01` : `SUM(this.attributions.heures) + heures <= this.heuresPrevues` - Warning si `heures > personne.heuresRestantesFormation()` Effet : INSERT attribution + recalcul rollups en cascade. ### Tache.creerIntervention(personne, heures, date) Verifications : - `personne.roles.contains(Role.developpeur)` — sinon throw - `heures > 0` - `personne.statut == actif` Effet : INSERT intervention + recalcul rollups (tache, projet, personne). ## 5. Patterns OO appliques | Pattern | Ou | Pourquoi | |---------|-----|----------| | **Value Object** | Email, Decimal heures, Filiere, Type, Priorite | Immutables, validation a la construction | | **State Pattern** | Statut sur toutes les entites avec cycle de vie | Encapsule transitions valides | | **Repository** | PersonneRepo, ProjetRepo, etc. | Abstrait l'acces Baserow API | | **Factory** | Module.creerAttribution(), Tache.creerIntervention() | Encapsule logique creation + validations | | **Observer** | Webhooks Baserow → bridge listeners | Evenements rollup → recalculs | | **Strategy** | Calcul capacite Personne (split formation/agence) | Permet de varier la regle (ex: split par periode) | ## 6. Mapping vers le code du bridge service (Phase 2) ```typescript // bridge/src/domain/personne.ts import { Decimal } from 'decimal.js'; export type Role = 'formateur' | 'developpeur' | 'admin' | 'direction' | 'support'; export class Personne { constructor( public readonly id: number, public nom: string, public prenom: string, public email: string, public capaciteAnnuelle: Decimal, public splitFormationPct: Decimal, public splitAgencePct: Decimal, public roles: Set, public statut: 'actif' | 'inactif', private _heuresAttribueesFormation: Decimal, private _heuresAttribueesAgence: Decimal, ) { if (!this.splitFormationPct.plus(this.splitAgencePct).equals(100)) { throw new Error('Splits doivent sommer a 100'); } } heuresRestantesFormation(): Decimal { const alloue = this.capaciteAnnuelle.times(this.splitFormationPct).div(100); return alloue.minus(this._heuresAttribueesFormation); } heuresRestantesAgence(): Decimal { const alloue = this.capaciteAnnuelle.times(this.splitAgencePct).div(100); return alloue.minus(this._heuresAttribueesAgence); } heuresRestantesTotal(): Decimal { return this.capaciteAnnuelle.minus(this._heuresAttribueesFormation).minus(this._heuresAttribueesAgence); } // ... } ``` ## 7. Limites du class diagram - Ne montre pas la persistence (deja fait par MLD) - Ne montre pas les sequences (deja fait par UML use cases sequence diagrams) - Redondant avec MCD sur les attributs simples C'est intentionnel : chaque vue eclaire un angle different. Le class diagram = angle **comportemental statique cote code**.