330 lines
28 KiB
Markdown
330 lines
28 KiB
Markdown
# review.md — Journal des décisions EME
|
|
|
|
> Ce fichier trace chaque étape réalisée et chaque choix technique, avec sa justification.
|
|
> Il est mis à jour au fil de l'avancement. Lecture du plus ancien (haut) au plus récent (bas).
|
|
>
|
|
> Règles métier -> `docs/regles-metier/regles-gestion.md` · Contexte -> `CONTEXT.md` · Plan -> `TODO.md`
|
|
|
|
---
|
|
|
|
## Conventions et choix transverses
|
|
|
|
Ces décisions s'appliquent à tout le projet, sauf mention contraire.
|
|
|
|
| Décision | Pourquoi |
|
|
|---|---|
|
|
| Statuts métier en `String` côté Prisma (pas d'enum natif) | SQL Server ne supporte pas les enums Prisma. Les valeurs sont validées côté TypeScript via `src/models/enums.ts`. |
|
|
| Timestamps automatiques : `createdAt @default(now())`, `updatedAt @updatedAt` | Évite d'avoir à fournir ces valeurs manuellement ; `updatedAt` est géré par Prisma au runtime. |
|
|
| `actif Boolean @default(true)` | Une entité créée est active par défaut. |
|
|
| `@unique` sur les identifiants fonctionnels | Intégrité : un identifiant en double casse l'authentification / l'unicité métier. |
|
|
| Champs nullable selon les cardinalités `0..1` du diagramme de classes | Un champ non connu à la création (ex. date de retour) ou optionnel doit être `NULL`, sinon le workflow métier est bloqué. |
|
|
| `onDelete: NoAction, onUpdate: NoAction` sur les données de traçabilité (Emprunt, Checklist, ChecklistElement, Anomalie, Historique) | Ces données ne doivent jamais être supprimées/altérées automatiquement en cascade. Toute suppression sera explicite côté service. Évite aussi l'erreur SQL Server "multiple cascade paths". |
|
|
| ERD tenu à jour en miroir du schéma (`docs/conceptions/uml/ERD.md`) | La source de vérité doit refléter le code réel (nullable, `UK`, etc.). |
|
|
| Workflow Git : `develop` comme branche d'intégration + branches dédiées `feat/...`, `fix/...`, `docs/...` | `master` reste figé ; chaque changement logique est isolé sur une branche puis mergé dans `develop`, conformément à `CLAUDE.md`. |
|
|
| Process avant chaque migration : `prisma format` -> `prisma validate` -> `npm run build` -> migration | Détecter toute erreur de schéma/typage avant de toucher la base. |
|
|
| DTO nommés `XxxResponse` (sortie) et `XxxRequest` (entrée) | Le sens est explicite dans le nom. Sortie = mapping (`toXxxResponse`), entrée = validation. |
|
|
|
|
---
|
|
|
|
## État actuel synthétique
|
|
|
|
Cette section résume l'état courant du projet. Le journal chronologique plus bas conserve
|
|
l'historique complet, y compris des étapes devenues obsolètes après branchement API.
|
|
|
|
| Bloc | État | Commentaire |
|
|
|---|---|---|
|
|
| Infrastructure | Terminé | Docker Compose SQL Server + Adminer, monorepo, backend Node/TS, frontend Flutter Web. |
|
|
| Base de données | Terminé pour la V1 | Schéma Prisma 16 entités, migrations, seeds et fixtures de démonstration. |
|
|
| API étudiant | Terminé pour la V1 | Catalogue, détail matériel, création d'emprunt, mes emprunts, restitution, anomalie automatique. |
|
|
| Frontend étudiant | Terminé pour la V1 | Parcours emprunt et restitution branchés sur l'API et testés en réel. |
|
|
| Authentification | Simulée | `x-user-email` côté backend et identité démo côté frontend ; Azure AD reste à faire. |
|
|
| Responsable matériel | Non démarré | Dashboard, stock, anomalies, historique à développer. |
|
|
| Tests automatisés | Non démarré | Tests backend/frontend/E2E à ajouter ; tests runtime manuels effectués. |
|
|
| Documentation | Partielle | `CONTEXT.md`, `TODO.md`, `review.md` existent ; README principal et OpenAPI restent à créer. |
|
|
|
|
## Commandes validées
|
|
|
|
Commandes utilisées et validées dans l'environnement de développement local :
|
|
|
|
```bash
|
|
docker compose up -d
|
|
cd eme-backend
|
|
npm run dev
|
|
npm run build
|
|
npm run lint
|
|
npm run seed
|
|
npm run fixtures
|
|
cd ../eme-frontend
|
|
flutter run -d web-server --web-port 5000
|
|
```
|
|
|
|
Notes :
|
|
- le backend écoute sur `http://localhost:3000` ;
|
|
- le frontend web de démo écoute sur `http://localhost:5000` ;
|
|
- Adminer est disponible sur `http://localhost:8081` ;
|
|
- dans l'environnement Codex, `flutter analyze`, `flutter analyze --no-pub` et `dart format` ont déjà bloqué au timeout ; à relancer dans un terminal local Flutter.
|
|
|
|
## Scénario de démo validé
|
|
|
|
Scénario étudiant validé avec SQL Server Docker et backend compilé :
|
|
|
|
1. Afficher le catalogue des matériels disponibles du campus.
|
|
2. Ouvrir le détail d'un matériel et vérifier les accessoires.
|
|
3. Créer un emprunt avec checklist de départ.
|
|
4. Vérifier que l'emprunt apparaît dans `mes-emprunts`.
|
|
5. Restituer conforme : l'emprunt passe `CLOTURE` et le matériel redevient disponible.
|
|
6. Restituer non conforme : l'emprunt passe `RETOUR_NON_CONFORME` et le matériel sort du catalogue disponible.
|
|
|
|
### Note outillage — migrations en environnement non-interactif
|
|
|
|
`prisma migrate dev` se bloque quand il doit demander une confirmation (ex. ajout de contrainte `@unique` sur table existante) car le terminal est non-interactif.
|
|
Contournement utilisé : générer le SQL avec `prisma migrate diff --from-config-datasource --to-schema ... --script`, écrire le fichier de migration, puis appliquer avec `prisma migrate deploy`. Résultat strictement identique à `migrate dev`, sans perte de données.
|
|
En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y`).
|
|
|
|
---
|
|
|
|
## Journal chronologique
|
|
|
|
### Étape 0 — Audit initial
|
|
- Constat : Block 0 (bootstrap) terminé mais non coché ; schéma à 4/16 entités ; aucune migration ; aucun commit Git.
|
|
- Décision : compléter le schéma par petits blocs (et non d'un coup) pour valider/committer au fur et à mesure.
|
|
|
|
### Étape 1 — Configuration des migrations Prisma
|
|
- Correction `DATABASE_URL` (mot de passe désaligné avec `DB_PASSWORD`).
|
|
- Découverte : Prisma 7 interdit `url` dans `schema.prisma` -> la connexion vit dans `prisma.config.ts`. Ligne `url` retirée du datasource.
|
|
|
|
### Étape 2 — Modèles de référence (Campus, Role, Utilisateur, CategorieMateriel)
|
|
- Defaults + timestamps auto ajoutés sur Campus, Utilisateur, CategorieMateriel (Role n'a pas de timestamps -> non modifié).
|
|
- `@unique` sur `Role.code`, `Utilisateur.microsoftId`, `Utilisateur.email`.
|
|
- `Utilisateur.classe` -> nullable : un `RESPONSABLE` n'a pas de classe (seuls les étudiants en ont).
|
|
- Ajout dans l'ERD des annotations `UK` (sur `code`, `microsoft_id`, `email`) et `nullable` (sur `classe`).
|
|
- Choix laissé de côté : tailles `@db.NVarChar(n)` (colonnes restées en `NVARCHAR(1000)` par défaut). À reconsidérer plus tard.
|
|
|
|
### Étape 3 — Bloc A : Infrastructure (SallePret, PosteEmprunt) — commit `d026b75`
|
|
- `SallePret` rattachée à `Campus` (FK `campus_id`) ; `PosteEmprunt` rattaché à `SallePret` (FK `salle_pret_id`).
|
|
|
|
### Étape 4 — Bloc B : CarteEtudiante — commit `dfa73cd`
|
|
- Rattachée à `Utilisateur`.
|
|
- Dette notée : `qr_code` devrait être `@unique` (sert à l'identification, RG02) — non posé pour rester fidèle à l'ERD.
|
|
|
|
### Étape 5 — Bloc C : Matériel (Materiel, Accessoire, MaterielAccessoire) — commit `0774ee3`
|
|
- Table de liaison `MaterielAccessoire` entre `Materiel` et `Accessoire`, sans colonnes `created_at`/`updated_at`.
|
|
- Dette notée : `@@unique([materielId, accessoireId])` et `Materiel.statut @default("DISPONIBLE")`.
|
|
|
|
### Étape 6 — Bloc D : Transactions (Emprunt, Checklist, ChecklistElement) — commit `6908a2b`
|
|
- Champs de retour/optionnels nullable : `dateRetourReelle`, `modeIdentificationRetour`, `commentaireDepart`, `commentaireRetour`, `Checklist.commentaire`, `ChecklistElement.commentaire`.
|
|
- Pourquoi : RG12 crée l'emprunt au départ ; les infos de retour n'existent pas encore. En `NOT NULL`, la création serait impossible.
|
|
- `ChecklistElement.accessoireId` rendu nullable : un élément de checklist peut être un libellé libre, sans accessoire catalogué associé (cardinalité 0..1).
|
|
- Les 9 FK en `NoAction` : traçabilité + évitement des cascade paths.
|
|
- Annotation `nullable` ajoutée dans l'ERD sur les champs de retour/commentaires d'`Emprunt` et `accessoire_id`/`commentaire` de checklist.
|
|
|
|
### Étape 7 — Stratégie Git : branche `develop`
|
|
- Création de `develop` depuis `master`. Désormais tous les commits vont sur `develop` ; `master` figé au Bloc C.
|
|
|
|
### Étape 8 — Bloc E : Suivi (Anomalie, Notification, Historique) — commit `0fc9f9e`
|
|
- Schéma 16/16 complet.
|
|
- Nullable selon `0..1` : `Anomalie.traiteeParId` (null tant que non pris en charge), `observation`, `dateResolution` ; `Notification.anomalieId` ; les 5 FK optionnelles d'`Historique` (un événement n'a pas toujours d'emprunt/matériel/etc.).
|
|
- Double relation `Anomalie` vers `Utilisateur` nommée : `@relation("AnomalieEtudiant")` (étudiant concerné) et `@relation("AnomalieResponsable")` (responsable qui traite).
|
|
- Defaults : `Anomalie.detecteeAutomatiquement @default(true)`, `Notification.lu @default(false)`, `Notification.dateCreation @default(now())`.
|
|
- Les 12 FK en `NoAction` (traçabilité).
|
|
- `Notification` et `Historique` créées sans colonne `updatedAt` (seulement `date_creation`/`created_at`).
|
|
- Annotation `nullable` ajoutée dans l'ERD sur `traitee_par_id`, `observation`, `date_resolution`, `anomalie_id` et les 5 FK optionnelles d'`Historique`.
|
|
|
|
### Étape 9 — Seeds de référence — commit `2c3a5db`
|
|
- Fichier `prisma/seed.ts` autonome (adapter MSSQL, lecture directe des variables DB), lancé via `npm run seed` (script ajouté au `package.json`).
|
|
- Choix `npm run seed` (ts-node) plutôt que `prisma db seed` : l'API de configuration du seed en Prisma 7 (`prisma.config.ts`) n'étant pas confirmée, un script direct est plus fiable.
|
|
- Données : 2 rôles (`ETUDIANT`, `RESPONSABLE`), 1 campus (`Campus Saint-Christophe`, Cergy, 95800, adresse provisoire), 1 salle (`Salle de prêt principale`), 1 poste (`POSTE-01`), 6 catégories (Ordinateur portable, Vidéoprojecteur, Tablette, Caméra, Périphérique audio, Câble / Adaptateur).
|
|
- Idempotence : `upsert` sur `Role.code` ; `findFirst` avant `create` pour les entités sans clé unique. Relance vérifiée (aucun doublon).
|
|
- Incident : le client Prisma était obsolète (ne connaissait que les 4 modèles de référence). Régénéré avec `npx prisma generate` avant le seed. Leçon : après des migrations, régénérer/vérifier le client avant d'exécuter du code qui l'utilise.
|
|
|
|
### Étape 10 — Fixtures de test
|
|
- Fichier `prisma/fixtures.ts` + script `npm run fixtures` (séparé du seed : données de dev/test, non installées en production).
|
|
- Non destructif : détection via un email témoin (`marie.dupont@ensitech.eu`) ; si présent, le script s'arrête (cohérent avec le principe "pas de suppression automatique").
|
|
- Contenu : 4 utilisateurs (3 étudiants + 1 responsable), 3 cartes, 6 matériels (statuts variés), 3 accessoires + liaisons, 4 emprunts couvrant `EN_COURS` / `EN_RETARD` / `CLOTURE` / `RETOUR_NON_CONFORME`, 6 checklists, 1 anomalie + 1 notification, 2 entrées d'historique.
|
|
- Idempotence vérifiée (2e exécution = skip).
|
|
|
|
#### Contexte métier clarifié — structure ENSUP (impacte la modélisation)
|
|
- ENSUP est un groupe **multi-campus** (Saint-Christophe/Cergy, Saint-Quentin, Nantes, Marseille...).
|
|
- Chaque campus héberge **deux écoles** : ENSUP (filières généralistes) et Ensitech (informatique). Bâtiments et salles **partagés**.
|
|
- La distinction d'école se fait par le **domaine email** : `ensitech.eu` (info) et `ensup.eu` (reste). La validation de domaine (RG, à venir) doit accepter les **deux**.
|
|
- Le modèle n'a pas d'entité "École" : seule `Campus` existe. Un campus = un lieu physique partagé par les deux écoles (et non une école).
|
|
- MVP : on démarre avec le **seul campus Saint-Christophe (Cergy)** ; les autres campus viendront ensuite.
|
|
|
|
### Étape 11 — Block 1 : middlewares backend
|
|
- Structure en couches : `utils/logger.ts`, `errors/app-error.ts`, `middlewares/` (request-logger, not-found, error-handler).
|
|
- Gestionnaire d'erreurs global : une `AppError` renvoie son statut + message ; toute autre erreur devient une 500 (stack exposée uniquement en `development`) et est tracée.
|
|
- Logger de requêtes (méthode, URL, statut, durée) + logger applicatif horodaté.
|
|
- CORS restreint à `env.frontendUrl` (était ouvert à toutes les origines). `SIGTERM` géré en plus de `SIGINT` (arrêt propre du container Docker).
|
|
- Express 5 propage nativement les erreurs des handlers async : pas de wrapper `asyncHandler` nécessaire.
|
|
- Vérifié au runtime : `/health` 200, route inconnue 404 en JSON, requêtes journalisées.
|
|
|
|
### Étape 12 — Block 1 : ESLint + Prettier
|
|
- ESLint 10 (flat config `eslint.config.mjs`) + typescript-eslint 8 ; Prettier 3 (`.prettierrc.json`).
|
|
- Règles de qualité strictes encodées : `no-explicit-any`, `no-non-null-assertion`, `explicit-module-boundary-types`, `no-unused-vars` (ignore le préfixe `_`), `prefer-const`. `eslint-config-prettier` désactive les règles en conflit avec Prettier.
|
|
- Prettier : quotes simples, point-virgule, 100 colonnes, 2 espaces, trailing commas.
|
|
- Scripts : `lint`, `lint:fix`, `format`, `format:check`.
|
|
- État : lint vert sur tout le code existant ; formatage appliqué (3 fichiers) ; build OK.
|
|
|
|
### Étape 13 — Correctif tooling : type-check des scripts Prisma
|
|
- Problème : `prisma/seed.ts` et `fixtures.ts` étaient hors du `include` du tsconfig ; l'IDE ne chargeait pas les types Node (`process` non reconnu, 2 erreurs).
|
|
- Correctif : `tsconfig.json` élargi à `src` + `prisma` en `noEmit` (IDE et `tsc --noEmit`) ; nouveau `tsconfig.build.json` dédié à la compilation `src` -> `dist` (`npm run build`).
|
|
- Bénéfice : les scripts Prisma sont désormais type-checkés (angle mort comblé).
|
|
|
|
### Étape 14 — Block 4 : architecture en couches + 1er endpoint (catalogue matériel)
|
|
- Mise en place de l'architecture en couches : `routes/` -> `controllers/` -> `services/` -> `repositories/` (un dossier par couche).
|
|
- Auth simulée temporaire : middleware `current-user` qui résout l'utilisateur via l'en-tête `x-user-email` et pose `req.user` (typé via `types/authenticated-user.ts` + augmentation `Express.Request`). À remplacer par la validation JWT au Block 3.
|
|
- Endpoint `GET /api/materiels` (catalogue) : applique RG10 (matériels `DISPONIBLE` du campus de l'étudiant), filtres `categorieId` et `q` (recherche nom/marque/modèle/référence).
|
|
- Format de réponse standardisé : `{ "data": ... }` (cohérent avec `{ "error": ... }`).
|
|
- Vérifié au runtime : 401 sans en-tête / utilisateur inconnu, 200 avec les disponibles du campus, filtres OK, 400 sur `categorieId` invalide.
|
|
|
|
### Étape 15 — Block 4 : endpoint "mes emprunts en cours"
|
|
- Endpoint `GET /api/mes-emprunts` : retourne les emprunts non restitués (`EN_COURS`, `EN_RETARD`) de l'utilisateur courant, triés par date de retour prévue, avec le matériel et sa catégorie inclus.
|
|
- RG15 : filtrage par `utilisateurId` (chacun ne voit que ses propres emprunts).
|
|
- Réutilise l'architecture en couches et l'auth simulée déjà en place.
|
|
- Vérifié au runtime : Marie 1 (`EN_COURS`, son `CLOTURE` exclu), Lucas 1 (`EN_RETARD`), Sofia 0 (son `RETOUR_NON_CONFORME` exclu), 401 sans en-tête.
|
|
|
|
### Étape 16 — Block 4 : profil et identification
|
|
- `GET /api/auth/me` (protégé) : renvoie le profil complet de l'utilisateur courant (role + campus).
|
|
- `GET /api/auth/carte/:qr` (public) : identification par QR code (RG02/RG03) ; contrôles carte active, non expirée et compte actif ; renvoie le profil.
|
|
- Refactor du routage : `currentUser` appliqué par sous-routeur (au lieu d'un middleware global) pour laisser la route d'identification publique.
|
|
- Vérifié au runtime : `/me` 200 (profil Marie) et 401 sans en-tête ; `/carte` QR valide 200 sans en-tête (route publique), QR inconnu 404.
|
|
|
|
### Étape 17 — DTO de sortie sur les endpoints existants
|
|
- Dossier `src/dtos/` : par ressource, une interface `XxxResponse` + un mapper pur `toXxxResponse` (utilisateur, matériel, emprunt).
|
|
- Mapping effectué dans le controller (couche présentation) ; les services continuent de renvoyer les entités (réutilisables).
|
|
- Champs internes désormais masqués : `microsoftId`, timestamps, FK brutes, `numeroInventaire`/`numeroSerie`.
|
|
- Vérifié au runtime sur `/me`, `/materiels`, `/mes-emprunts`.
|
|
|
|
### Étape 18 — Durcissement du .gitignore (sécurité)
|
|
- Trou comblé : `**/.env` ne couvrait pas les variantes (`.env.local`, `.env.production`...). Ajout de `**/.env.*` avec exception `!**/.env.example`.
|
|
- Préventif : clés/certificats (`*.pem`, `*.key`, `*.crt`, `*.cert`, `*.pfx`, `*.p12`) pour Azure AD/TLS à venir ; dumps de base (`*.bak`, `*.dump`) ; `**/coverage/` ; `*.tsbuildinfo`.
|
|
- Vérifié : aucun secret n'était déjà suivi ; les vrais `.env` restent ignorés ; `.env.example` (placeholders) reste versionné.
|
|
|
|
### Étape 19 — Block 4 : création d'emprunt (POST /api/emprunts)
|
|
- Écriture transactionnelle : réservation atomique du matériel (`updateMany where statut=DISPONIBLE`), création de l'emprunt (`EN_COURS`), de la checklist de départ et de ses éléments. Rollback global si une étape échoue.
|
|
- Règles : RG07 (matériel disponible), RG10 (matériel du campus de l'étudiant), RG11 (checklist obligatoire non vide), RG12 (matériel -> `EMPRUNTE`, horodatage).
|
|
- Validation d'entrée manuelle (`CreerEmpruntRequest`, `parseCreerEmpruntRequest`) : aucune dépendance ajoutée. Durée d'emprunt par défaut : +14 jours.
|
|
- Contrôle du poste (existe + même campus, RG05). Routage : `POST /api/emprunts` et `GET /api/mes-emprunts` sur des routeurs séparés.
|
|
- Vérifié au runtime : 401 sans auth, 400 checklist vide, 404 matériel inconnu, 201 création (matériel -> `EMPRUNTE`, +14j), 409 doublon (réservation atomique).
|
|
|
|
### Étape 20 — Block 4 : restitution + anomalie automatique (POST /api/emprunts/:id/restitution)
|
|
- Comparaison automatique départ/retour (RG17) : un élément présent au départ mais absent/détérioré au retour rend la restitution non conforme (RG20). Appariement par `accessoireId` sinon par `nomElement`.
|
|
- Restitution atomique : checklist de retour + mise à jour emprunt/matériel + (si non conforme) anomalie `DETECTEE` + notifications.
|
|
- RG15 (propriétaire), statut restituable, RG18 (conforme -> `CLOTURE` + matériel `DISPONIBLE`), RG19 (non conforme -> `RETOUR_NON_CONFORME` + matériel `DETERIORE`/`NON_CONFORME`).
|
|
- RG24 : notification à tous les responsables (`RESPONSABLE`) du campus de l'emprunt.
|
|
- Vérifié au runtime : 404/403/409 ; restitution conforme (CLOTURE + DISPONIBLE) ; non conforme (RETOUR_NON_CONFORME + NON_CONFORME + anomalie + notification à Karim).
|
|
- **Block 4 (API Étudiant) terminé : 6/6 endpoints.**
|
|
|
|
### Étape 21 — Frontend : setup Flutter Web + écran d'accueil ENSUP
|
|
- Projet Flutter Web créé (`eme-frontend/`), `google_fonts` ajouté (Darker Grotesque pour les titres, Titillium Web pour le corps).
|
|
- Thème ENSUP (`theme/ensup_colors.dart`, `theme/ensup_theme.dart`) : couleurs de la charte graphique.
|
|
- Composants réutilisables : `EnsupTopBar`, `ProfileCard`, `ActionCard`.
|
|
- Écran d'accueil (`screens/home_screen.dart`) fidèle à la maquette : topbar bleu foncé, carte profil, deux cartes Emprunter/Restituer. Données statiques (pas encore branché à l'API).
|
|
- Convention `CLAUDE.md` respectée : guillemets doubles en Dart (règle lint `prefer_single_quotes` désactivée en conséquence).
|
|
- `flutter analyze` : aucun problème. App lancée dans Chrome (http://localhost:5000).
|
|
|
|
### Étape 22 — Suppression du PDF de charte graphique
|
|
- PDF de charte ENSUP retiré du dépôt (redondant : la maquette validée applique la charte, et les couleurs/typos sont dans `CONTEXT.md` §7).
|
|
- Références mises à jour dans `CLAUDE.md` et `CONTEXT.md` pour pointer vers la maquette.
|
|
- Le PDF reste récupérable dans l'historique Git si besoin (logo officiel source).
|
|
|
|
### Étape 23 — Frontend : écran d'identification (écran de démarrage)
|
|
- Correction : l'écran de démarrage est l'identification (`s-login` de la maquette), pas l'accueil étudiant. Logo, "Bienvenue sur EME", deux options (scanner carte / compte ENSUP Microsoft 365), bouton accès responsable.
|
|
- `EnsupTopBar` rendue réutilisable (utilisateur optionnel, marque paramétrable) ; nouveau widget `IdentificationOption` ; coins ENSUP aussi sur cet écran.
|
|
- Navigation identification -> accueil étudiant (`HomeScreen`).
|
|
|
|
### Étape 24 — Frontend : écran catalogue matériel
|
|
- Écran catalogue (`s-catalogue`) : recherche **fonctionnelle** + filtres par catégorie (chips) + liste de matériels avec statut (Disponible/Emprunté) et état vide.
|
|
- Nouveaux composants : `MaterielCard`, `StatusPill`, modèle `MaterielItem`. Données statiques (4 matériels de la maquette).
|
|
- Navigation : Accueil (Emprunter) -> Catalogue ; bouton retour vers l'accueil. « Sélectionner » -> placeholder (détail à venir).
|
|
|
|
### Étape 25 — Frontend : écran détail matériel
|
|
- Écran détail (`s-detail`) : caractéristiques (référence, catégorie, marque, modèle, état, campus, statut) + accessoires du kit (tags) + aperçu + boutons « Démarrer l'emprunt » / « Retour au catalogue ».
|
|
- Modèle `MaterielItem` enrichi (marque, modèle, état, accessoires) ; données statiques mises à jour.
|
|
- Navigation : Catalogue (Sélectionner) -> Détail ; « Démarrer l'emprunt » -> placeholder (checklist à venir).
|
|
|
|
> Note historique : les étapes 21 à 25 décrivent l'état initial statique du frontend.
|
|
> Elles ont été remplacées fonctionnellement par les branchements API des étapes 26 à 32.
|
|
|
|
---
|
|
|
|
## Dette technique en attente
|
|
|
|
À traiter ensemble plus tard (avec mise à jour ERD en miroir) :
|
|
|
|
| Dette | Statut | Impact V1 |
|
|
|---|---|---|
|
|
| `CarteEtudiante.qr_code` -> `@unique` | À faire avec migration + ERD | Moyen : sécurise l'identification QR. |
|
|
| `MaterielAccessoire` -> `@@unique([materielId, accessoireId])` | À faire avec migration + ERD | Moyen : évite les doublons d'accessoires. |
|
|
| `Materiel.statut` -> `@default("DISPONIBLE")` | À faire avec migration + ERD | Faible : le code fournit déjà le statut explicitement. |
|
|
| Tailles de colonnes `@db.NVarChar(n)` | À cadrer | Faible V1, important pour qualité BDD. |
|
|
| Swagger/OpenAPI | À faire | Moyen : utile pour tester/documenter l'API. |
|
|
| Auth réelle Azure AD | À faire | Fort : requis pour sortir de la démo avec auth simulée. |
|
|
| Limite d'emprunts actifs par étudiant | À valider métier | Non bloquant V1 ; décision métier non présente dans les règles actuelles. |
|
|
|
|
---
|
|
|
|
### Étape 26 — Connexion frontend ↔ API (catalogue)
|
|
- Package `http` ajouté. Couche `services/api_client.dart` : URL de base, en-tête d'auth simulée (`x-user-email: lucas.martin@ensitech.eu`), gestion des erreurs (serveur injoignable, message `{error:{message}}`).
|
|
- `services/materiel_service.dart` (`getCatalogue`) + `MaterielItem.fromJson` (icône déduite de la catégorie, champs absents complétés).
|
|
- Écran catalogue branché via `FutureBuilder` : chargement / données / erreur + bouton Réessayer. Filtres de catégorie déduits des vraies données.
|
|
- CORS backend assoupli en développement (`origin: true` si `NODE_ENV=development`), strict en production.
|
|
- Testé en réel côté backend : Docker SQL Server OK, backend compilé OK, `/health`, `/api/auth/me`, `/api/materiels` OK, 401 sans `x-user-email` OK.
|
|
|
|
### Étape 27 — Connexion frontend ↔ API (détail matériel)
|
|
- Correctif runtime backend : `npm run dev` lance maintenant `ts-node --files`, sinon l'augmentation `Express.Request.user` n'était pas chargée par `ts-node` malgré un build TypeScript vert.
|
|
- Endpoint `GET /api/materiels/:id` ajouté : détail filtré par campus utilisateur, avec catégorie, campus et accessoires du kit.
|
|
- Frontend : `MaterielItem` porte maintenant l'`id`, `MaterielService.getDetail(id)` consomme le nouvel endpoint, et le catalogue charge le détail réel avant de naviguer vers l'écran détail.
|
|
- Testé en réel côté backend : `/api/materiels/1` renvoie le PC avec accessoires (`Chargeur`, `Souris`) ; `/api/materiels/abc` renvoie 400.
|
|
- Limite environnement : `flutter analyze`, `flutter analyze --no-pub` et `dart format` restent bloqués jusqu'au timeout dans le sandbox. À relancer dans un terminal Flutter local.
|
|
|
|
### Étape 28 — Connexion frontend ↔ API (création d'emprunt)
|
|
- Branche dédiée `feat/frontend-emprunt-api` créée après merge de `feat/catalogue-detail-api` dans `develop`.
|
|
- `ApiClient.post` ajouté et `EmpruntService.creerEmprunt` consomme `POST /api/emprunts` avec l'auth simulée.
|
|
- Checklist de départ branchée sur l'API : construction du payload (`materielId`, `posteEmpruntId`, `modeIdentification`, commentaire, éléments), état de chargement, affichage d'erreur via snackbar.
|
|
- Un matériel sans accessoire génère un élément de checklist portant le nom du matériel, afin de respecter RG11 côté backend (checklist obligatoire non vide).
|
|
- Confirmation alimentée par la réponse API (`id`, `dateEmprunt`, matériel renvoyé).
|
|
- Testé sans mutation de données : `POST /api/emprunts` avec checklist vide renvoie bien 400 `La checklist de depart est obligatoire (RG11)`.
|
|
|
|
### Étape 29 — Données de démonstration catalogue
|
|
- Branche dédiée `feat/demo-catalogue-fixtures` créée après merge de `feat/frontend-emprunt-api` dans `develop`.
|
|
- `prisma/fixtures.ts` enrichi avec un catalogue de démonstration idempotent : si les fixtures de base existent déjà, le script assure seulement les matériels de catalogue manquants.
|
|
- 8 matériels disponibles ajoutés : Lenovo ThinkPad, MacBook Air, Surface Pro, vidéoprojecteur Epson, caméra Canon, casque Jabra, kit câbles HDMI/USB-C, enceinte JBL.
|
|
- Accessoires associés assurés sans doublon logique par recherche de nom/référence avant création.
|
|
- Vérifié en réel : `npm run fixtures` OK ; `GET /api/materiels` pour Lucas renvoie 10 matériels disponibles.
|
|
|
|
### Étape 30 — Connexion frontend ↔ API (restitution)
|
|
- Branche dédiée `feat/frontend-restitution-api` créée après merge de `feat/demo-catalogue-fixtures` dans `develop`.
|
|
- `EmpruntItem.fromJson` ajouté pour mapper `GET /api/mes-emprunts`.
|
|
- `EmpruntService.getMesEmprunts()` et `EmpruntService.restituerEmprunt()` ajoutés.
|
|
- Écran de sélection restitution branché sur les vrais emprunts en cours, avec chargement, erreur, état vide et chargement du détail matériel avant la checklist.
|
|
- Checklist retour branchée sur `POST /api/emprunts/:id/restitution`, avec commentaire optionnel, état de chargement et erreurs via snackbar.
|
|
- Le résultat affiché se base sur le statut renvoyé par le backend (`CLOTURE` => conforme, sinon anomalie), afin de rester cohérent avec la comparaison serveur.
|
|
- Vérifié sans mutation : `GET /api/mes-emprunts` renvoie les emprunts de Lucas ; restitution d'un identifiant inexistant renvoie 404.
|
|
|
|
### Étape 31 — Stabilisation parcours étudiant complet
|
|
- Branche dédiée `feat/student-flow-stabilization` créée après merge de `feat/frontend-restitution-api` dans `develop`.
|
|
- Docker SQL Server relancé puis tests runtime faits avec le backend compilé.
|
|
- Flux conforme validé en réel : catalogue -> détail -> création emprunt -> apparition dans `mes-emprunts` -> restitution conforme -> statut `CLOTURE` -> matériel de nouveau visible dans le catalogue.
|
|
- Flux non conforme validé en réel : création emprunt -> restitution avec élément absent -> statut `RETOUR_NON_CONFORME` -> matériel retiré du catalogue disponible.
|
|
- Aucun correctif code nécessaire après ces tests ; backend `build` et `lint` restent verts.
|
|
|
|
### Étape 32 — Polish V1 étudiant
|
|
- Branche dédiée `feat/v1-student-polish` créée après merge de `feat/student-flow-stabilization` dans `develop`.
|
|
- Identité simulée et campus MVP centralisés dans `lib/demo_identity.dart` tant que l'auth Azure AD n'est pas branchée.
|
|
- Libellés UI harmonisés sur le contexte réel du MVP : `Saint-Christophe · Cergy` / `Ensitech Cergy` au lieu de `Paris · Ensitech`.
|
|
- Commentaire obsolète du modèle `MaterielItem` corrigé : les données viennent maintenant de l'API.
|
|
- `TODO.md` mis à jour : les parcours emprunt et restitution étudiant sont maintenant branchés API.
|
|
|
|
### Étape 33 — Clarification du journal de décisions
|
|
- Branche dédiée `docs/review-current-state` créée depuis `develop`.
|
|
- Ajout d'une synthèse d'état courant pour éviter de devoir relire tout l'historique.
|
|
- Correction de la convention Git : `develop` est la branche d'intégration, les travaux passent par branches dédiées.
|
|
- Ajout des commandes validées et du scénario de démo étudiant testé.
|
|
- Dette technique reformatée en tableau avec statut et impact V1.
|
|
- Clarification des étapes frontend statiques historiques : elles sont conservées pour mémoire mais remplacées par les branchements API ultérieurs.
|
|
|
|
---
|
|
|
|
*Dernière mise à jour : 2026-07-09 — État courant du projet et journal de décisions clarifiés.*
|