|
|
|
|
|
# 🗺️ Roadmap Application Legacy BricoLoc
|
|
|
|
|
|
|
|
|
|
|
|
**Objectif** : Créer une réplique simplifiée mais fidèle de l'architecture monolithique existante de BricoLoc (2013-2025) pour démontrer les problématiques techniques et architecturales.
|
|
|
|
|
|
|
|
|
|
|
|
**Durée** : 2 semaines (Semaines 3-4 du projet global)
|
|
|
|
|
|
**Effort** : 40 heures
|
|
|
|
|
|
**Stack technique** : Node.js, Express.js, EJS, SQLite, Sessions
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## <20> État d'Avancement
|
|
|
|
|
|
|
|
|
|
|
|
**Dernière mise à jour** : 28 Octobre 2025
|
|
|
|
|
|
|
|
|
|
|
|
| Phase | Statut | Progression | Temps estimé |
|
|
|
|
|
|
|-------|--------|-------------|--------------|
|
|
|
|
|
|
| **Jour 1 - Setup Initial** | ✅ Complété | 100% | 4h |
|
|
|
|
|
|
| **Jour 2 - Authentification** | ✅ Complété | 100% | 4h |
|
|
|
|
|
|
| **Jour 3 - Catalogue** | ✅ Complété | 100% | 4h |
|
|
|
|
|
|
| **Jour 4 - Réservations** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 5 - Administration** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 6 - UI/UX** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 7 - Gestion Stocks** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 8 - Calendrier** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 9 - Features Secondaires** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
| **Jour 10 - Tests & Docs** | 🔲 Non commencé | 0% | 4h |
|
|
|
|
|
|
|
|
|
|
|
|
**Progression globale** : 🟩🟩🟩🟩🟩🟩⬜⬜⬜⬜ 30% (3/10 jours complétés)
|
|
|
|
|
|
|
|
|
|
|
|
### ✅ Ce qui est fait (Jours 1-3)
|
|
|
|
|
|
|
|
|
|
|
|
**Jour 1 - Infrastructure** :
|
|
|
|
|
|
- ✅ Structure complète du projet (16 fichiers créés)
|
|
|
|
|
|
- ✅ Configuration package.json et dépendances installées
|
|
|
|
|
|
- ✅ Base de données SQLite initialisée (6 tables)
|
|
|
|
|
|
- ✅ Scripts d'initialisation et de seeding fonctionnels
|
|
|
|
|
|
- ✅ Templates EJS de base (layout, index, partials/messages)
|
|
|
|
|
|
- ✅ CSS legacy old-school
|
|
|
|
|
|
- ✅ Module database.js avec fonctions utilitaires
|
|
|
|
|
|
- ✅ 2 utilisateurs de test créés (admin + standard)
|
|
|
|
|
|
|
|
|
|
|
|
**Jour 2 - Authentification** :
|
|
|
|
|
|
- ✅ Routes : `/login`, `/register`, `/logout`
|
|
|
|
|
|
- ✅ Templates : `login.ejs`, `register.ejs`
|
|
|
|
|
|
- ✅ Logique d'authentification avec sessions
|
|
|
|
|
|
- ✅ Middleware `requireAuth`
|
|
|
|
|
|
- ✅ **Bugs intentionnels** : mot de passe en clair, pas de CSRF, validation email
|
|
|
|
|
|
|
|
|
|
|
|
**Jour 3 - Catalogue** :
|
|
|
|
|
|
- ✅ 20 outils créés avec catégories, marques, descriptions
|
|
|
|
|
|
- ✅ 10 entrepôts dans différentes villes
|
|
|
|
|
|
- ✅ 12 catégories d'outils
|
|
|
|
|
|
- ✅ Stocks générés pour chaque outil/entrepôt
|
|
|
|
|
|
- ✅ Routes GET `/outils` et GET `/outils/:id`
|
|
|
|
|
|
- ✅ Filtres : catégorie, recherche, prix min/max
|
|
|
|
|
|
- ✅ Templates `outils.ejs` et `outil-detail.ejs`
|
|
|
|
|
|
- ✅ CSS complet pour grille d'outils et fiches détail
|
|
|
|
|
|
- ✅ Partials header/footer réutilisables
|
|
|
|
|
|
- ✅ **Bugs intentionnels** : SQL injection (BUG-003), N+1 queries (BUG-012), pas de pagination DB (BUG-011), logique dans templates (BUG-017)
|
|
|
|
|
|
|
|
|
|
|
|
### 🎯 Prochaine étape (Jour 4)
|
|
|
|
|
|
|
|
|
|
|
|
**Implémenter le système de réservations** :
|
|
|
|
|
|
- Routes : `/login`, `/register`, `/logout`
|
|
|
|
|
|
- Templates : `login.ejs`, `register.ejs`
|
|
|
|
|
|
- Logique d'authentification avec sessions
|
|
|
|
|
|
- Middleware `requireAuth`
|
|
|
|
|
|
- **Bugs intentionnels** : mot de passe en clair, pas de CSRF, validation email
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## <20>📋 Contexte et Objectifs
|
|
|
|
|
|
|
|
|
|
|
|
### Système Actuel BricoLoc (Architecture Complète)
|
|
|
|
|
|
|
|
|
|
|
|
**Architecture technique historique** :
|
|
|
|
|
|
- **Frontend** : Java Spring Framework 5, Tomcat 8.5, services web SOAP
|
|
|
|
|
|
- **Backend** : Java EE 6 (EJB, JPA), WebLogic Server 12c R1
|
|
|
|
|
|
- **Base de données** : Oracle 11g R2 (bricolocDB), MySQL 5 (cache)
|
|
|
|
|
|
- **Écosystème SI** :
|
|
|
|
|
|
- ERP SAP Business One 9.X
|
|
|
|
|
|
- Comparateur de prix SaaS (API REST)
|
|
|
|
|
|
- Batch Java de synchronisation CSV nocturne
|
|
|
|
|
|
- Client lourd C# pour gestion stocks entrepôts
|
|
|
|
|
|
- Power BI pour analytics
|
|
|
|
|
|
- Outils Python d'analyse
|
|
|
|
|
|
- **Problèmes identifiés** :
|
|
|
|
|
|
- "Grande boule de boue" (monolithe chaotique)
|
|
|
|
|
|
- Logique métier éparpillée (backend, PL/SQL, frontend)
|
|
|
|
|
|
- Accès direct à la DB depuis le frontend (contournement du backend)
|
|
|
|
|
|
- Tables avec >150 colonnes
|
|
|
|
|
|
- Dérives architecturales depuis 2013
|
|
|
|
|
|
- Bugs et problèmes de performance
|
|
|
|
|
|
- Incohérences majeures sur la gestion des stocks
|
|
|
|
|
|
|
|
|
|
|
|
### Périmètre de la Réplique Legacy (Phase 1)
|
|
|
|
|
|
|
|
|
|
|
|
> **🎯 Focus** : Application web B2C uniquement (MVP en 2 semaines)
|
|
|
|
|
|
|
|
|
|
|
|
Créer une application **Node.js/Express** qui :
|
|
|
|
|
|
1. ✅ Reproduit les fonctionnalités principales (catalogue, réservations, admin)
|
|
|
|
|
|
2. ✅ Intègre **intentionnellement** les anti-patterns et bugs typiques
|
|
|
|
|
|
3. ✅ Démontre les limites d'une architecture monolithique mal maintenue
|
|
|
|
|
|
4. ✅ Sert de point de comparaison avec l'application moderne
|
|
|
|
|
|
|
|
|
|
|
|
**Ce qui EST inclus (Phase 1)** :
|
|
|
|
|
|
- ✅ Application web B2C (frontend + backend monolithique)
|
|
|
|
|
|
- ✅ Authentification et gestion utilisateurs
|
|
|
|
|
|
- ✅ Catalogue d'outils avec filtres
|
|
|
|
|
|
- ✅ Système de réservations
|
|
|
|
|
|
- ✅ Gestion des stocks (simplifiée)
|
|
|
|
|
|
- ✅ Interface admin (CRUD outils, stocks)
|
|
|
|
|
|
- ✅ Architecture monolithique avec bugs intentionnels
|
|
|
|
|
|
|
|
|
|
|
|
**Ce qui N'EST PAS inclus (Extensions futures)** :
|
|
|
|
|
|
- ⏸️ Backend séparé avec services SOAP/REST
|
|
|
|
|
|
- ⏸️ Cache MySQL séparé
|
|
|
|
|
|
- ⏸️ Procédures PL/SQL (logique dans la DB)
|
|
|
|
|
|
- ⏸️ Intégration ERP (SAP Business One simulé)
|
|
|
|
|
|
- ⏸️ Comparateur de prix externe (API)
|
|
|
|
|
|
- ⏸️ Batch de synchronisation CSV/Java
|
|
|
|
|
|
- ⏸️ Client lourd C# pour stocks entrepôts
|
|
|
|
|
|
- ⏸️ Power BI / Analytics dashboard
|
|
|
|
|
|
- ⏸️ Vraie intégration Stripe (paiement)
|
|
|
|
|
|
- ⏸️ Chat support temps réel
|
|
|
|
|
|
|
|
|
|
|
|
**Simplifications acceptées** :
|
|
|
|
|
|
- Node.js au lieu de Java (plus accessible pour la démo)
|
|
|
|
|
|
- SQLite au lieu d'Oracle (simplicité de déploiement)
|
|
|
|
|
|
- Monolithe unique au lieu de frontend/backend séparés
|
|
|
|
|
|
- Pas de services SOAP (architecture simplifiée)
|
|
|
|
|
|
- Pas de cache MySQL séparé (inutile pour la démo)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 Fonctionnalités à Implémenter
|
|
|
|
|
|
|
|
|
|
|
|
### Périmètre Fonctionnel (MVP)
|
|
|
|
|
|
|
|
|
|
|
|
| Module | Fonctionnalités | Priorité |
|
|
|
|
|
|
|--------|-----------------|----------|
|
|
|
|
|
|
| **Authentification** | Inscription, Connexion, Sessions | 🔴 Critique |
|
|
|
|
|
|
| **Catalogue** | Liste des outils, Détails outil, Filtres basiques | 🔴 Critique |
|
|
|
|
|
|
| **Réservations** | Créer réservation, Voir mes réservations, Annuler | 🔴 Critique |
|
|
|
|
|
|
| **Administration** | CRUD outils, Gestion stocks, Liste réservations | 🟠 Important |
|
|
|
|
|
|
| **Chat Support** | Simulacre de chat (messages statiques) | 🟢 Nice-to-have |
|
|
|
|
|
|
|
|
|
|
|
|
### User Stories (7 US Principales)
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L01 : Inscription Utilisateur
|
|
|
|
|
|
**En tant que** visiteur
|
|
|
|
|
|
**Je veux** créer un compte
|
|
|
|
|
|
**Afin de** pouvoir réserver des outils
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Formulaire avec email, mot de passe, nom, prénom
|
|
|
|
|
|
- ❌ **BUG** : Pas de validation format email
|
|
|
|
|
|
- ❌ **BUG** : Mot de passe stocké en clair dans la DB
|
|
|
|
|
|
- ❌ **BUG** : Pas de confirmation de mot de passe
|
|
|
|
|
|
- ✅ Redirection vers `/login` après inscription
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L02 : Connexion Utilisateur
|
|
|
|
|
|
**En tant que** utilisateur enregistré
|
|
|
|
|
|
**Je veux** me connecter
|
|
|
|
|
|
**Afin de** accéder à mon espace client
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Formulaire avec email et mot de passe
|
|
|
|
|
|
- ✅ Session persistante (cookie)
|
|
|
|
|
|
- ❌ **BUG** : Pas de protection CSRF
|
|
|
|
|
|
- ❌ **BUG** : Messages d'erreur trop détaillés (fuite d'info)
|
|
|
|
|
|
- ✅ Redirection vers `/outils` après connexion
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L03 : Consulter le Catalogue
|
|
|
|
|
|
**En tant que** visiteur ou utilisateur
|
|
|
|
|
|
**Je veux** voir la liste des outils disponibles
|
|
|
|
|
|
**Afin de** choisir un outil à louer
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Liste paginée des outils (20 par page)
|
|
|
|
|
|
- ✅ Filtres : catégorie, prix min/max, disponibilité
|
|
|
|
|
|
- ❌ **BUG** : Pas de pagination côté serveur (tout chargé en mémoire)
|
|
|
|
|
|
- ❌ **BUG** : Requête SQL vulnérable aux injections (filtres)
|
|
|
|
|
|
- ✅ Affichage : nom, prix/jour, catégorie, image
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L04 : Consulter Détails d'un Outil
|
|
|
|
|
|
**En tant que** visiteur ou utilisateur
|
|
|
|
|
|
**Je veux** voir les détails d'un outil
|
|
|
|
|
|
**Afin de** décider si je veux le réserver
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Description complète, prix, caractéristiques
|
|
|
|
|
|
- ✅ Images de l'outil
|
|
|
|
|
|
- ✅ Calendrier de disponibilité (si connecté)
|
|
|
|
|
|
- ❌ **BUG** : Calendrier n'affiche pas toutes les réservations (bug de calcul de dates)
|
|
|
|
|
|
- ❌ **BUG** : Prix affiché peut être incohérent avec le calcul final
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L05 : Créer une Réservation
|
|
|
|
|
|
**En tant que** utilisateur connecté
|
|
|
|
|
|
**Je veux** réserver un outil pour des dates précises
|
|
|
|
|
|
**Afin de** l'utiliser pour mon projet
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Formulaire : date début, date fin, entrepôt de retrait
|
|
|
|
|
|
- ✅ Calcul automatique du prix total
|
|
|
|
|
|
- ❌ **BUG** : Pas de vérification de disponibilité réelle (race condition)
|
|
|
|
|
|
- ❌ **BUG** : Double-booking possible
|
|
|
|
|
|
- ❌ **BUG** : Prix calculé côté client (manipulable)
|
|
|
|
|
|
- ✅ Confirmation de réservation affichée
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L06 : Voir Mes Réservations
|
|
|
|
|
|
**En tant que** utilisateur connecté
|
|
|
|
|
|
**Je veux** voir l'historique de mes réservations
|
|
|
|
|
|
**Afin de** suivre mes locations en cours et passées
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ Liste des réservations (en cours, passées, annulées)
|
|
|
|
|
|
- ✅ Détails : outil, dates, prix, statut, entrepôt
|
|
|
|
|
|
- ✅ Bouton "Annuler" (si réservation à venir)
|
|
|
|
|
|
- ❌ **BUG** : Annulation ne libère pas le stock immédiatement
|
|
|
|
|
|
- ❌ **BUG** : Dates affichées avec timezone incorrect
|
|
|
|
|
|
|
|
|
|
|
|
#### US-L07 : Administration des Outils (Admin)
|
|
|
|
|
|
**En tant qu'** administrateur
|
|
|
|
|
|
**Je veux** gérer le catalogue d'outils
|
|
|
|
|
|
**Afin de** maintenir l'inventaire à jour
|
|
|
|
|
|
|
|
|
|
|
|
**Critères d'acceptation** :
|
|
|
|
|
|
- ✅ CRUD complet : Créer, Modifier, Supprimer des outils
|
|
|
|
|
|
- ✅ Gestion des stocks par entrepôt
|
|
|
|
|
|
- ✅ Upload d'images
|
|
|
|
|
|
- ❌ **BUG** : Pas de vérification des permissions (n'importe qui peut devenir admin)
|
|
|
|
|
|
- ❌ **BUG** : Suppression d'outil ne vérifie pas les réservations actives
|
|
|
|
|
|
- ❌ **BUG** : Interface admin accessible via URL directe sans authentification forte
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🏗️ Architecture Technique Détaillée
|
|
|
|
|
|
|
|
|
|
|
|
### Stack Technique
|
|
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
Runtime: Node.js 20+
|
|
|
|
|
|
Framework Web: Express.js 4.x
|
|
|
|
|
|
Template Engine: EJS (Embedded JavaScript)
|
|
|
|
|
|
Base de données: SQLite 3
|
|
|
|
|
|
Gestion de sessions: express-session + SQLite store
|
|
|
|
|
|
Upload fichiers: multer
|
|
|
|
|
|
Sécurité: AUCUNE (volontairement)
|
|
|
|
|
|
Tests: AUCUN (volontairement)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Structure du Projet
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
apps/legacy-app/
|
|
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── server.js # Point d'entrée, TOUT le code backend
|
|
|
|
|
|
│ ├── database.js # Connexion SQLite + requêtes
|
|
|
|
|
|
│ ├── views/ # Templates EJS
|
|
|
|
|
|
│ │ ├── layout.ejs # Layout principal
|
|
|
|
|
|
│ │ ├── index.ejs # Page d'accueil
|
|
|
|
|
|
│ │ ├── login.ejs # Connexion
|
|
|
|
|
|
│ │ ├── register.ejs # Inscription
|
|
|
|
|
|
│ │ ├── outils.ejs # Liste des outils
|
|
|
|
|
|
│ │ ├── outil-detail.ejs # Détails d'un outil
|
|
|
|
|
|
│ │ ├── reservations.ejs # Mes réservations
|
|
|
|
|
|
│ │ ├── nouvelle-reservation.ejs # Formulaire réservation
|
|
|
|
|
|
│ │ ├── admin/
|
|
|
|
|
|
│ │ │ ├── dashboard.ejs # Dashboard admin
|
|
|
|
|
|
│ │ │ ├── outils.ejs # Gestion outils
|
|
|
|
|
|
│ │ │ ├── stocks.ejs # Gestion stocks
|
|
|
|
|
|
│ │ │ └── reservations.ejs # Liste réservations
|
|
|
|
|
|
│ │ └── partials/
|
|
|
|
|
|
│ │ ├── header.ejs
|
|
|
|
|
|
│ │ ├── footer.ejs
|
|
|
|
|
|
│ │ └── messages.ejs # Flash messages
|
|
|
|
|
|
│ ├── public/ # Assets statiques
|
|
|
|
|
|
│ │ ├── css/
|
|
|
|
|
|
│ │ │ └── styles.css # CSS global (minimal, old-school)
|
|
|
|
|
|
│ │ ├── js/
|
|
|
|
|
|
│ │ │ └── main.js # JavaScript client (jQuery style)
|
|
|
|
|
|
│ │ └── images/
|
|
|
|
|
|
│ │ ├── logo.png
|
|
|
|
|
|
│ │ └── outils/ # Images des outils
|
|
|
|
|
|
│ └── uploads/ # Uploads dynamiques
|
|
|
|
|
|
├── docs/
|
|
|
|
|
|
│ ├── ROADMAP_LEGACY.md # Ce fichier
|
|
|
|
|
|
│ ├── BUGS.md # Liste exhaustive des bugs
|
|
|
|
|
|
│ └── ARCHITECTURE.md # Schéma de l'architecture
|
|
|
|
|
|
├── data/
|
|
|
|
|
|
│ ├── bricoloc.db # Base SQLite
|
|
|
|
|
|
│ └── seeds/
|
|
|
|
|
|
│ ├── entrepots.sql
|
|
|
|
|
|
│ ├── categories.sql
|
|
|
|
|
|
│ ├── outils.sql
|
|
|
|
|
|
│ └── users.sql
|
|
|
|
|
|
├── package.json
|
|
|
|
|
|
└── README.md
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Modèle de Données (SQLite)
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `users`
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE users (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
email TEXT NOT NULL UNIQUE,
|
|
|
|
|
|
password TEXT NOT NULL, -- ❌ En clair !
|
|
|
|
|
|
nom TEXT NOT NULL,
|
|
|
|
|
|
prenom TEXT NOT NULL,
|
|
|
|
|
|
telephone TEXT,
|
|
|
|
|
|
adresse TEXT,
|
|
|
|
|
|
code_postal TEXT,
|
|
|
|
|
|
ville TEXT,
|
|
|
|
|
|
is_admin INTEGER DEFAULT 0, -- ❌ Pas de gestion de rôles
|
|
|
|
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `categories`
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE categories (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
nom TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
slug TEXT UNIQUE
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `entrepots`
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE entrepots (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
nom TEXT NOT NULL,
|
|
|
|
|
|
ville TEXT NOT NULL,
|
|
|
|
|
|
code_postal TEXT,
|
|
|
|
|
|
adresse TEXT,
|
|
|
|
|
|
telephone TEXT,
|
|
|
|
|
|
email TEXT
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `outils`
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE outils (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
nom TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
categorie_id INTEGER,
|
|
|
|
|
|
prix_jour REAL NOT NULL,
|
|
|
|
|
|
caution REAL,
|
|
|
|
|
|
marque TEXT,
|
|
|
|
|
|
modele TEXT,
|
|
|
|
|
|
annee INTEGER,
|
|
|
|
|
|
poids REAL,
|
|
|
|
|
|
dimensions TEXT,
|
|
|
|
|
|
puissance TEXT,
|
|
|
|
|
|
image_url TEXT,
|
|
|
|
|
|
restrictions_pro INTEGER DEFAULT 0,
|
|
|
|
|
|
livraison_possible INTEGER DEFAULT 1,
|
|
|
|
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
FOREIGN KEY (categorie_id) REFERENCES categories(id)
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `stocks` (Anti-pattern : données dénormalisées)
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE stocks (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
outil_id INTEGER NOT NULL,
|
|
|
|
|
|
entrepot_id INTEGER NOT NULL,
|
|
|
|
|
|
quantite_totale INTEGER NOT NULL,
|
|
|
|
|
|
quantite_disponible INTEGER NOT NULL, -- ❌ Calculé manuellement, source de bugs
|
|
|
|
|
|
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
FOREIGN KEY (outil_id) REFERENCES outils(id),
|
|
|
|
|
|
FOREIGN KEY (entrepot_id) REFERENCES entrepots(id)
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Table `reservations`
|
|
|
|
|
|
```sql
|
|
|
|
|
|
CREATE TABLE reservations (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
|
user_id INTEGER NOT NULL,
|
|
|
|
|
|
outil_id INTEGER NOT NULL,
|
|
|
|
|
|
entrepot_id INTEGER NOT NULL,
|
|
|
|
|
|
date_debut DATE NOT NULL,
|
|
|
|
|
|
date_fin DATE NOT NULL,
|
|
|
|
|
|
prix_total REAL NOT NULL, -- ❌ Calculé côté client
|
|
|
|
|
|
statut TEXT DEFAULT 'en_attente', -- en_attente, confirmee, annulee, terminee
|
|
|
|
|
|
mode_paiement TEXT, -- en_ligne, entrepot
|
|
|
|
|
|
paiement_effectue INTEGER DEFAULT 0,
|
|
|
|
|
|
notes TEXT,
|
|
|
|
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
|
|
|
|
FOREIGN KEY (outil_id) REFERENCES outils(id),
|
|
|
|
|
|
FOREIGN KEY (entrepot_id) REFERENCES entrepots(id)
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🐛 Bugs et Anti-Patterns Intentionnels
|
|
|
|
|
|
|
|
|
|
|
|
### Liste des 15+ Bugs à Implémenter
|
|
|
|
|
|
|
|
|
|
|
|
| ID | Catégorie | Description | Impact | Fichier |
|
|
|
|
|
|
|----|-----------|-------------|--------|---------|
|
|
|
|
|
|
| **BUG-001** | Sécurité | Mot de passe en clair dans DB | 🔴 Critique | `database.js` |
|
|
|
|
|
|
| **BUG-002** | Sécurité | Pas de protection CSRF | 🔴 Critique | `server.js` |
|
|
|
|
|
|
| **BUG-003** | Sécurité | SQL Injection sur filtres | 🔴 Critique | `server.js` (route `/outils`) |
|
|
|
|
|
|
| **BUG-004** | Sécurité | Admin accessible sans auth forte | 🔴 Critique | `server.js` (middleware) |
|
|
|
|
|
|
| **BUG-005** | Sécurité | Upload fichiers non sécurisé | 🟠 Élevé | `server.js` (multer) |
|
|
|
|
|
|
| **BUG-006** | Validation | Pas de validation format email | 🟠 Élevé | `server.js` (POST `/register`) |
|
|
|
|
|
|
| **BUG-007** | Validation | Prix calculé côté client | 🔴 Critique | `nouvelle-reservation.ejs` |
|
|
|
|
|
|
| **BUG-008** | Logique | Race condition sur réservations | 🔴 Critique | `server.js` (POST `/reservations`) |
|
|
|
|
|
|
| **BUG-009** | Logique | Double-booking possible | 🔴 Critique | `server.js` (vérification dispo) |
|
|
|
|
|
|
| **BUG-010** | Logique | Annulation ne libère pas le stock | 🟠 Élevé | `server.js` (DELETE `/reservations/:id`) |
|
|
|
|
|
|
| **BUG-011** | Performance | Pas de pagination DB | 🟠 Élevé | `server.js` (GET `/outils`) |
|
|
|
|
|
|
| **BUG-012** | Performance | Requêtes N+1 | 🟠 Élevé | `server.js` (boucles imbriquées) |
|
|
|
|
|
|
| **BUG-013** | UX | Messages d'erreur trop détaillés | 🟡 Moyen | `login.ejs` |
|
|
|
|
|
|
| **BUG-014** | UX | Dates avec timezone incorrect | 🟡 Moyen | `reservations.ejs` |
|
|
|
|
|
|
| **BUG-015** | Code | Code dupliqué partout | 🟠 Élevé | `server.js` (>1000 lignes) |
|
|
|
|
|
|
| **BUG-016** | Code | Pas de gestion d'erreurs try/catch | 🟠 Élevé | `server.js` (global) |
|
|
|
|
|
|
| **BUG-017** | Architecture | Logique métier dans les vues EJS | 🔴 Critique | `outils.ejs`, `reservations.ejs` |
|
|
|
|
|
|
| **BUG-018** | Architecture | Tout dans un seul fichier | 🔴 Critique | `server.js` (monolithe) |
|
|
|
|
|
|
|
|
|
|
|
|
**Documentation complète** : Voir [`BUGS.md`](./BUGS.md)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📅 Planning Détaillé (2 Semaines)
|
|
|
|
|
|
|
|
|
|
|
|
### Semaine 3 : Backend + Fonctionnalités Principales (20h)
|
|
|
|
|
|
|
|
|
|
|
|
#### ✅ Jour 1 (Lundi) - Setup Initial (4h) - COMPLÉTÉ
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Initialiser le projet Node.js
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd apps/legacy-app
|
|
|
|
|
|
npm init -y
|
|
|
|
|
|
npm install express ejs express-session sqlite3 multer express-flash connect-sqlite3
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Créer la structure de fichiers
|
|
|
|
|
|
```bash
|
|
|
|
|
|
mkdir -p src/views/{admin,partials} src/public/{css,js,images/outils} src/uploads data/seeds docs
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Configurer `server.js` (fichier principal monolithique)
|
|
|
|
|
|
- ✅ Setup Express + EJS
|
|
|
|
|
|
- ✅ Configuration sessions (cookie-based, pas de JWT)
|
|
|
|
|
|
- ✅ Middleware basique (body-parser, static)
|
|
|
|
|
|
- **BUG-002** : Pas de helmet, pas de CSRF protection
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Créer `database.js`
|
|
|
|
|
|
- ✅ Connexion SQLite
|
|
|
|
|
|
- ✅ Fonctions utilitaires (query, run, all)
|
|
|
|
|
|
- ✅ **BUG-001** : Fonction `createUser()` stocke mot de passe en clair
|
|
|
|
|
|
|
|
|
|
|
|
5. ✅ Créer le schéma de base de données
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm run db:init # Script créé et fonctionnel
|
|
|
|
|
|
npm run db:seed # 2 utilisateurs de test créés
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Serveur Express structure créée (server.js placeholder)
|
|
|
|
|
|
- ✅ Base SQLite initialisée avec schéma complet (6 tables)
|
|
|
|
|
|
- ✅ Structure de fichiers complète (16 fichiers créés)
|
|
|
|
|
|
- ✅ Templates EJS : layout.ejs, index.ejs, partials/messages.ejs
|
|
|
|
|
|
- ✅ CSS legacy old-school (styles.css)
|
|
|
|
|
|
- ✅ Scripts d'initialisation DB fonctionnels
|
|
|
|
|
|
|
|
|
|
|
|
**Statut** : ✅ **JOUR 1 COMPLÉTÉ** - Structure complète opérationnelle
|
|
|
|
|
|
|
|
|
|
|
|
**Prochaine étape** : Jour 2 - Implémenter l'authentification complète (routes + logique)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### ✅ Jour 2 (Mardi) - Authentification (4h) - COMPLÉTÉ
|
|
|
|
|
|
|
|
|
|
|
|
**User Stories** : US-L01, US-L02
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Créer les routes d'authentification
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
// server.js
|
|
|
|
|
|
app.get('/login', (req, res) => { ... });
|
|
|
|
|
|
app.post('/login', (req, res) => { ... });
|
|
|
|
|
|
app.get('/register', (req, res) => { ... });
|
|
|
|
|
|
app.post('/register', (req, res) => { ... });
|
|
|
|
|
|
app.get('/logout', (req, res) => { ... });
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Créer les templates EJS
|
|
|
|
|
|
- ✅ `views/login.ejs` : formulaire de connexion avec layout complet
|
|
|
|
|
|
- ✅ `views/register.ejs` : formulaire d'inscription avec tous les champs
|
|
|
|
|
|
- ✅ `views/layout.ejs` : layout principal (déjà créé)
|
|
|
|
|
|
- ✅ `views/index.ejs` : mise à jour avec layout complet
|
|
|
|
|
|
- ✅ Navigation dynamique selon statut login
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Implémenter la logique d'authentification
|
|
|
|
|
|
- ✅ Vérification email/password (en clair)
|
|
|
|
|
|
- ✅ Création de session (stockage user_id dans SQLite store)
|
|
|
|
|
|
- ✅ **BUG-006** : Pas de validation format email
|
|
|
|
|
|
- ✅ **BUG-013** : Messages d'erreur détaillés ("Email introuvable" vs "Mot de passe incorrect")
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Créer le middleware d'authentification
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
function requireAuth(req, res, next) {
|
|
|
|
|
|
if (!req.session.userId) {
|
|
|
|
|
|
return res.redirect('/login');
|
|
|
|
|
|
}
|
|
|
|
|
|
next();
|
|
|
|
|
|
}
|
|
|
|
|
|
// ❌ BUG-004 : Pas de middleware requireAdmin séparé
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Inscription fonctionnelle (avec bugs intentionnels)
|
|
|
|
|
|
- ✅ Connexion fonctionnelle (avec bugs intentionnels)
|
|
|
|
|
|
- ✅ Sessions persistantes avec SQLite store
|
|
|
|
|
|
- ✅ Logout qui détruit la session
|
|
|
|
|
|
- ✅ Menu de navigation dynamique (connecté/non connecté)
|
|
|
|
|
|
- ✅ Lien "Administration" visible pour les admins
|
|
|
|
|
|
|
|
|
|
|
|
**Tests manuels effectués** :
|
|
|
|
|
|
- ✅ Créer un compte test@test.com → ✅ Inscrit correctement
|
|
|
|
|
|
- ✅ Se connecter avec admin@bricoloc.fr → ✅ Session créée
|
|
|
|
|
|
- ✅ Vérifier menu admin → ✅ Lien "Administration" visible
|
|
|
|
|
|
- ✅ Vérifier DB → ✅ Mot de passe en clair confirmé (BUG-001)
|
|
|
|
|
|
- ✅ Session persiste entre les requêtes → ✅ Cookie valide 7 jours
|
|
|
|
|
|
|
|
|
|
|
|
**Statut** : ✅ **JOUR 2 COMPLÉTÉ** - Authentification fonctionnelle avec bugs intentionnels
|
|
|
|
|
|
|
|
|
|
|
|
**Prochaine étape** : Jour 3 - Implémenter le catalogue d'outils avec filtres
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### 🔲 Jour 3 (Mercredi) - Catalogue d'outils (4h) - À FAIRE
|
|
|
|
|
|
|
|
|
|
|
|
**Statut** : ⏸️ **À FAIRE** - Prochaine étape du développement
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### 🔲 Jour 3 (Mercredi) - Catalogue (4h) - NON COMMENCÉ
|
|
|
|
|
|
|
|
|
|
|
|
**User Stories** : US-L03, US-L04
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. 🔲 Seeder les données de test
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sqlite3 data/bricoloc.db < data/seeds/entrepots.sql
|
|
|
|
|
|
sqlite3 data/bricoloc.db < data/seeds/categories.sql
|
|
|
|
|
|
sqlite3 data/bricoloc.db < data/seeds/outils.sql
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Créer les routes catalogue
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
app.get('/outils', (req, res) => { ... }); // Liste
|
|
|
|
|
|
app.get('/outils/:id', (req, res) => { ... }); // Détails
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Implémenter la liste des outils
|
|
|
|
|
|
- Query SQL avec JOIN categories
|
|
|
|
|
|
- Filtres : catégorie, prix min/max, disponibilité
|
|
|
|
|
|
- **BUG-003** : SQL Injection via paramètres de filtre
|
|
|
|
|
|
- **BUG-011** : Pas de pagination, tout chargé en mémoire
|
|
|
|
|
|
- **BUG-012** : Requête N+1 pour les stocks
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Créer les templates
|
|
|
|
|
|
- `views/outils.ejs` : grille d'outils
|
|
|
|
|
|
- `views/outil-detail.ejs` : fiche détaillée
|
|
|
|
|
|
- **BUG-017** : Calculs de disponibilité dans le template EJS
|
|
|
|
|
|
|
|
|
|
|
|
5. ✅ CSS basique old-school
|
|
|
|
|
|
- `public/css/styles.css` : styles années 2010
|
|
|
|
|
|
- Pas de responsive design
|
|
|
|
|
|
- Tables pour layout (anti-pattern)
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Page catalogue fonctionnelle
|
|
|
|
|
|
- ✅ Page détail outil avec images
|
|
|
|
|
|
- ✅ Filtres fonctionnels (mais vulnérables)
|
|
|
|
|
|
|
|
|
|
|
|
**Tests manuels** :
|
|
|
|
|
|
- [ ] Injecter SQL dans filtre catégorie : `?categorie=1' OR '1'='1` → ✅ Fonctionne
|
|
|
|
|
|
- [ ] Charger 500+ outils → ✅ Lenteur visible
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 4 (Jeudi) - Réservations (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**User Stories** : US-L05, US-L06
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Créer les routes réservations
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
app.get('/outils/:id/reserver', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.post('/reservations', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.get('/mes-reservations', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.post('/reservations/:id/annuler', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Implémenter la création de réservation
|
|
|
|
|
|
- Formulaire : dates, entrepôt
|
|
|
|
|
|
- **BUG-007** : Prix total calculé côté client (JavaScript)
|
|
|
|
|
|
- **BUG-008** : Pas de transaction SQL (race condition)
|
|
|
|
|
|
- **BUG-009** : Vérification de disponibilité incomplète
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Implémenter la liste des réservations
|
|
|
|
|
|
- Query avec JOIN outils, entrepots
|
|
|
|
|
|
- **BUG-012** : Requête N+1 encore
|
|
|
|
|
|
- **BUG-014** : Dates affichées avec mauvais timezone
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Implémenter l'annulation
|
|
|
|
|
|
- Update statut = 'annulee'
|
|
|
|
|
|
- **BUG-010** : Ne met pas à jour `stocks.quantite_disponible`
|
|
|
|
|
|
|
|
|
|
|
|
5. ✅ Créer les templates
|
|
|
|
|
|
- `views/nouvelle-reservation.ejs` : formulaire avec calendrier
|
|
|
|
|
|
- `views/reservations.ejs` : liste des réservations
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Réservation fonctionnelle
|
|
|
|
|
|
- ✅ Historique des réservations
|
|
|
|
|
|
- ✅ Annulation fonctionnelle (mais buguée)
|
|
|
|
|
|
|
|
|
|
|
|
**Tests manuels** :
|
|
|
|
|
|
- [ ] Créer 2 réservations simultanées pour le même outil → ✅ Double-booking
|
|
|
|
|
|
- [ ] Annuler une réservation → ✅ Stock pas libéré
|
|
|
|
|
|
- [ ] Modifier le prix total dans le formulaire (DevTools) → ✅ Accepté
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 5 (Vendredi) - Administration Basique (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**User Stories** : US-L07 (partiel)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Créer les routes admin
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
app.get('/admin', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.get('/admin/outils', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.post('/admin/outils', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.post('/admin/outils/:id/supprimer', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Implémenter CRUD outils
|
|
|
|
|
|
- Formulaire création/édition
|
|
|
|
|
|
- Upload d'image (multer)
|
|
|
|
|
|
- **BUG-005** : Pas de validation du type de fichier
|
|
|
|
|
|
- **BUG-004** : Pas de vérification `is_admin`
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Créer les templates admin
|
|
|
|
|
|
- `views/admin/dashboard.ejs` : page d'accueil admin
|
|
|
|
|
|
- `views/admin/outils.ejs` : gestion des outils
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Seed un utilisateur admin
|
|
|
|
|
|
```sql
|
|
|
|
|
|
INSERT INTO users (email, password, nom, prenom, is_admin)
|
|
|
|
|
|
VALUES ('admin@bricoloc.fr', 'admin123', 'Admin', 'BricoLoc', 1);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Interface admin accessible (sans protection)
|
|
|
|
|
|
- ✅ CRUD outils fonctionnel
|
|
|
|
|
|
- ✅ Upload d'images fonctionnel (non sécurisé)
|
|
|
|
|
|
|
|
|
|
|
|
**Tests manuels** :
|
|
|
|
|
|
- [ ] Accéder à `/admin` sans être admin → ✅ Accès autorisé
|
|
|
|
|
|
- [ ] Uploader un fichier `.php` → ✅ Accepté
|
|
|
|
|
|
- [ ] Supprimer un outil avec réservations actives → ✅ Pas de vérification
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### Semaine 4 : Frontend, Gestion Stocks, Finitions (20h)
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 6 (Lundi) - Amélioration UI/UX (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Créer le CSS "old-school"
|
|
|
|
|
|
```css
|
|
|
|
|
|
/* public/css/styles.css */
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: Arial, sans-serif;
|
|
|
|
|
|
background: #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
table {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ❌ Pas de responsive, pas de flexbox/grid */
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Ajouter JavaScript côté client (jQuery-style)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
// public/js/main.js
|
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
|
// Calcul prix réservation (BUG-007)
|
|
|
|
|
|
$('#date_debut, #date_fin').change(function() {
|
|
|
|
|
|
var prixJour = parseFloat($('#prix_jour').val());
|
|
|
|
|
|
var nbJours = calculerNbJours();
|
|
|
|
|
|
$('#prix_total').val(prixJour * nbJours); // ❌ Manipulable
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Améliorer les templates existants
|
|
|
|
|
|
- Ajouter flash messages (succès, erreurs)
|
|
|
|
|
|
- Menu de navigation avec état connecté/déconnecté
|
|
|
|
|
|
- Breadcrumb basique
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Créer la page d'accueil
|
|
|
|
|
|
- `views/index.ejs` : landing page simple
|
|
|
|
|
|
- Liste des catégories populaires
|
|
|
|
|
|
- Section "Comment ça marche"
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Interface utilisateur basique mais complète
|
|
|
|
|
|
- ✅ Page d'accueil informative
|
|
|
|
|
|
- ✅ Navigation cohérente
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 7 (Mardi) - Gestion Stocks (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**User Stories** : US-L07 (complet)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Créer les routes gestion stocks
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
app.get('/admin/stocks', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
app.post('/admin/stocks/:id/update', requireAuth, (req, res) => { ... });
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Implémenter la logique de stocks
|
|
|
|
|
|
- Affichage stocks par entrepôt
|
|
|
|
|
|
- Modification manuelle des quantités
|
|
|
|
|
|
- **BUG-010** : Incohérence avec les réservations actives
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Créer le template
|
|
|
|
|
|
- `views/admin/stocks.ejs` : tableau de gestion
|
|
|
|
|
|
- Formulaire de modification en ligne
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Implémenter la vérification de disponibilité
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
function checkAvailability(outilId, dateDebut, dateFin, entrepotId) {
|
|
|
|
|
|
// ❌ BUG-009 : Logique incomplète, ne vérifie pas toutes les conditions
|
|
|
|
|
|
const query = `
|
|
|
|
|
|
SELECT quantite_disponible FROM stocks
|
|
|
|
|
|
WHERE outil_id = ? AND entrepot_id = ?
|
|
|
|
|
|
`;
|
|
|
|
|
|
// Ne prend pas en compte les réservations en conflit
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Interface de gestion des stocks
|
|
|
|
|
|
- ✅ Mise à jour manuelle des quantités
|
|
|
|
|
|
- ✅ Vérification de disponibilité (buguée)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 8 (Mercredi) - Calendrier Disponibilités (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Implémenter le calendrier sur la page détail outil
|
|
|
|
|
|
- Affichage des dates déjà réservées
|
|
|
|
|
|
- Sélection de plage de dates
|
|
|
|
|
|
- **BUG-014** : Problèmes de timezone
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Ajouter bibliothèque de calendrier (ex: flatpickr)
|
|
|
|
|
|
```html
|
|
|
|
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ JavaScript pour bloquer les dates indisponibles
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
flatpickr("#date_debut", {
|
|
|
|
|
|
disable: reservedDates, // ❌ BUG : Liste incomplète
|
|
|
|
|
|
minDate: "today"
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Améliorer le formulaire de réservation
|
|
|
|
|
|
- Sélection entrepôt
|
|
|
|
|
|
- Calcul prix dynamique (côté client, BUG-007)
|
|
|
|
|
|
- Récapitulatif avant validation
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Calendrier de réservation fonctionnel
|
|
|
|
|
|
- ✅ Expérience utilisateur améliorée
|
|
|
|
|
|
- ✅ Bugs de dates documentés
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 9 (Jeudi) - Features Secondaires (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Implémenter la recherche d'outils
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
app.get('/recherche', (req, res) => {
|
|
|
|
|
|
const q = req.query.q;
|
|
|
|
|
|
// ❌ BUG-003 : SQL Injection possible
|
|
|
|
|
|
const query = `SELECT * FROM outils WHERE nom LIKE '%${q}%'`;
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Ajouter pagination (côté client seulement)
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
// ❌ BUG-011 : Tout chargé en mémoire puis paginé en JS
|
|
|
|
|
|
const allOutils = await db.all('SELECT * FROM outils');
|
|
|
|
|
|
res.render('outils', { outils: allOutils }); // Pas de LIMIT
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Créer une page "Mes informations"
|
|
|
|
|
|
- Affichage des données utilisateur
|
|
|
|
|
|
- Formulaire de modification (non fonctionnel)
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Ajouter un simulacre de chat support
|
|
|
|
|
|
- Messages statiques prédéfinis
|
|
|
|
|
|
- Formulaire de contact (ne fait rien)
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Recherche fonctionnelle (vulnérable)
|
|
|
|
|
|
- ✅ Pagination côté client
|
|
|
|
|
|
- ✅ Pages secondaires complètes
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### Jour 10 (Vendredi) - Tests Manuels & Documentation (4h)
|
|
|
|
|
|
|
|
|
|
|
|
**Tâches** :
|
|
|
|
|
|
1. ✅ Tests manuels exhaustifs
|
|
|
|
|
|
- Parcourir tous les scénarios utilisateur
|
|
|
|
|
|
- Reproduire tous les bugs identifiés
|
|
|
|
|
|
- Documenter les comportements anormaux
|
|
|
|
|
|
|
|
|
|
|
|
2. ✅ Rédiger `docs/BUGS.md`
|
|
|
|
|
|
- Liste exhaustive des 18+ bugs
|
|
|
|
|
|
- Instructions de reproduction
|
|
|
|
|
|
- Captures d'écran si nécessaire
|
|
|
|
|
|
- Explications des impacts
|
|
|
|
|
|
|
|
|
|
|
|
3. ✅ Rédiger `docs/ARCHITECTURE.md`
|
|
|
|
|
|
- Schéma de l'architecture monolithique
|
|
|
|
|
|
- Flux de données
|
|
|
|
|
|
- Points de friction identifiés
|
|
|
|
|
|
|
|
|
|
|
|
4. ✅ Mettre à jour `README.md`
|
|
|
|
|
|
- Instructions d'installation
|
|
|
|
|
|
- Commandes de lancement
|
|
|
|
|
|
- Comptes de test (admin + utilisateur standard)
|
|
|
|
|
|
- Liste des fonctionnalités
|
|
|
|
|
|
|
|
|
|
|
|
5. ✅ Créer un seed complet
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm run seed # Script qui remplit la DB avec données de test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Livrables** :
|
|
|
|
|
|
- ✅ Application testée manuellement
|
|
|
|
|
|
- ✅ Documentation complète (BUGS.md, ARCHITECTURE.md)
|
|
|
|
|
|
- ✅ README.md à jour
|
|
|
|
|
|
- ✅ Données de test complètes
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 Métriques Cibles (Application Legacy)
|
|
|
|
|
|
|
|
|
|
|
|
### Métriques de Qualité (Volontairement Basses)
|
|
|
|
|
|
|
|
|
|
|
|
| Métrique | Cible | Méthode de Mesure |
|
|
|
|
|
|
|----------|-------|-------------------|
|
|
|
|
|
|
| **Lighthouse Performance** | < 60 | Chrome DevTools |
|
|
|
|
|
|
| **Lighthouse Best Practices** | < 70 | Chrome DevTools |
|
|
|
|
|
|
| **Lighthouse SEO** | < 80 | Chrome DevTools |
|
|
|
|
|
|
| **Tests Coverage** | 0% | Aucun test |
|
|
|
|
|
|
| **Complexité Cyclomatique** | > 20 | ESLint plugin |
|
|
|
|
|
|
| **Code Duplication** | > 30% | jscpd |
|
|
|
|
|
|
| **Lignes de code (server.js)** | > 1000 | wc -l |
|
|
|
|
|
|
| **Nombre de bugs identifiés** | > 15 | Documentation manuelle |
|
|
|
|
|
|
| **Time to Interactive (TTI)** | > 5s | Lighthouse |
|
|
|
|
|
|
|
|
|
|
|
|
### Métriques Fonctionnelles (Succès)
|
|
|
|
|
|
|
|
|
|
|
|
| Métrique | Cible |
|
|
|
|
|
|
|----------|-------|
|
|
|
|
|
|
| **User Stories implémentées** | 7/7 |
|
|
|
|
|
|
| **Fonctionnalités principales** | 100% |
|
|
|
|
|
|
| **Pages créées** | 12+ |
|
|
|
|
|
|
| **Templates EJS** | 15+ |
|
|
|
|
|
|
| **Routes Express** | 20+ |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 Critères de Succès
|
|
|
|
|
|
|
|
|
|
|
|
### Critères de Complétion
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ **7 User Stories** complètement implémentées et fonctionnelles
|
|
|
|
|
|
- ✅ **18+ bugs** identifiés, implémentés et documentés
|
|
|
|
|
|
- ✅ **Application déployable** localement sans erreur
|
|
|
|
|
|
- ✅ **Documentation complète** (BUGS.md, ARCHITECTURE.md, README.md)
|
|
|
|
|
|
- ✅ **Données de test** (seed complet avec 50+ outils, 10 entrepôts, 5 utilisateurs)
|
|
|
|
|
|
- ✅ **UI old-school** mais cohérente et navigable
|
|
|
|
|
|
|
|
|
|
|
|
### Critères de Qualité (Intentionnellement Bas)
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ **Aucun test** automatisé
|
|
|
|
|
|
- ✅ **Fichier monolithique** server.js > 1000 lignes
|
|
|
|
|
|
- ✅ **Vulnérabilités de sécurité** multiples
|
|
|
|
|
|
- ✅ **Performance médiocre** (temps de chargement > 3s)
|
|
|
|
|
|
- ✅ **Code legacy authentique** (duplication, pas de patterns)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🚀 Démarrage Rapide
|
|
|
|
|
|
|
|
|
|
|
|
### Installation
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd apps/legacy-app
|
|
|
|
|
|
npm install
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Initialisation de la base de données
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm run db:init # Crée le schéma
|
|
|
|
|
|
npm run db:seed # Remplit avec données de test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Lancement du serveur
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm start # Production
|
|
|
|
|
|
npm run dev # Développement (nodemon)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Accès à l'application
|
|
|
|
|
|
|
|
|
|
|
|
- **URL** : `http://localhost:3000`
|
|
|
|
|
|
- **Compte admin** : `admin@bricoloc.fr` / `admin123`
|
|
|
|
|
|
- **Compte utilisateur** : `jean.dupont@email.fr` / `password123`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📚 Ressources et Références
|
|
|
|
|
|
|
|
|
|
|
|
### Technologies Utilisées
|
|
|
|
|
|
|
|
|
|
|
|
- [Express.js Documentation](https://expressjs.com/)
|
|
|
|
|
|
- [EJS Documentation](https://ejs.co/)
|
|
|
|
|
|
- [SQLite Documentation](https://www.sqlite.org/docs.html)
|
|
|
|
|
|
- [Multer (File Upload)](https://github.com/expressjs/multer)
|
|
|
|
|
|
- [express-session](https://github.com/expressjs/session)
|
|
|
|
|
|
|
|
|
|
|
|
### Inspiration Architecture Legacy
|
|
|
|
|
|
|
|
|
|
|
|
- Article : [Big Ball of Mud](http://www.laputan.org/mud/)
|
|
|
|
|
|
- Article : [Monolith to Microservices](https://martinfowler.com/articles/break-monolith-into-microservices.html)
|
|
|
|
|
|
- Vidéo : [Legacy Code Patterns](https://www.youtube.com/watch?v=...)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔮 Extensions Futures (Phases 2-3)
|
|
|
|
|
|
|
|
|
|
|
|
> Ces fonctionnalités reproduisent plus fidèlement l'écosystème SI complet de BricoLoc.
|
|
|
|
|
|
> Elles peuvent être ajoutées après la Phase 1 pour enrichir la démo.
|
|
|
|
|
|
|
|
|
|
|
|
### Phase 2 : Backend Séparé & Intégrations (Optionnel - +20h)
|
|
|
|
|
|
|
|
|
|
|
|
**Objectif** : Reproduire l'architecture frontend/backend séparée avec services SOAP/REST
|
|
|
|
|
|
|
|
|
|
|
|
| Extension | Description | Effort | Priorité |
|
|
|
|
|
|
|-----------|-------------|--------|----------|
|
|
|
|
|
|
| **Backend API séparé** | Extraire la logique métier dans un service Node.js séparé (SOAP ou REST) | 8h | 🟠 Moyenne |
|
|
|
|
|
|
| **Cache MySQL** | Ajouter une base MySQL pour cache (photos, docs) | 3h | 🟢 Basse |
|
|
|
|
|
|
| **Procédures SQL** | Migrer une partie de la logique en procédures stockées SQLite | 4h | 🟡 Moyenne |
|
|
|
|
|
|
| **Batch de synchronisation** | Script Node.js simulant la synchro CSV nocturne des stocks | 5h | 🟠 Moyenne |
|
|
|
|
|
|
|
|
|
|
|
|
**Valeur ajoutée** :
|
|
|
|
|
|
- Démontre les problèmes de couplage frontend/backend
|
|
|
|
|
|
- Illustre la complexité des services web SOAP legacy
|
|
|
|
|
|
- Montre les difficultés de synchronisation de données
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### Phase 3 : Écosystème Complet (Optionnel - +30h)
|
|
|
|
|
|
|
|
|
|
|
|
**Objectif** : Simuler l'intégration avec les systèmes externes (ERP, comparateur, analytics)
|
|
|
|
|
|
|
|
|
|
|
|
| Extension | Description | Effort | Priorité |
|
|
|
|
|
|
|-----------|-------------|--------|----------|
|
|
|
|
|
|
| **Mock ERP (SAP B1)** | API REST simulant l'ERP avec données de stocks | 6h | 🟢 Basse |
|
|
|
|
|
|
| **Comparateur de prix** | Service externe (API) pour comparaison prix outils | 5h | 🟢 Basse |
|
|
|
|
|
|
| **Client lourd stocks** | Application Electron (ou CLI) pour gestion stocks entrepôts | 8h | 🟡 Moyenne |
|
|
|
|
|
|
| **Dashboard Analytics** | Page simple avec graphiques (Chart.js) simulant Power BI | 4h | 🟢 Basse |
|
|
|
|
|
|
| **Vraie intégration Stripe** | Paiement fonctionnel avec webhooks | 4h | 🟠 Moyenne |
|
|
|
|
|
|
| **Chat temps réel** | Socket.io pour chat support en temps réel | 3h | 🟢 Basse |
|
|
|
|
|
|
|
|
|
|
|
|
**Valeur ajoutée** :
|
|
|
|
|
|
- Reproduit la complexité d'un SI avec multiples systèmes
|
|
|
|
|
|
- Démontre les problèmes d'intégration et de cohérence des données
|
|
|
|
|
|
- Illustre les dépendances entre systèmes legacy
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### Roadmap d'Extensions (Si Temps Disponible)
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
gantt
|
|
|
|
|
|
title Extensions Legacy (Optionnel)
|
|
|
|
|
|
dateFormat YYYY-MM-DD
|
|
|
|
|
|
section Phase 1 (MVP)
|
|
|
|
|
|
App Web B2C :done, phase1, 2025-10-28, 2w
|
|
|
|
|
|
section Phase 2
|
|
|
|
|
|
Backend API séparé :crit, phase2a, after phase1, 8d
|
|
|
|
|
|
Cache MySQL :phase2b, after phase1, 3d
|
|
|
|
|
|
Procédures SQL :phase2c, after phase2a, 4d
|
|
|
|
|
|
Batch synchronisation :phase2d, after phase2b, 5d
|
|
|
|
|
|
section Phase 3
|
|
|
|
|
|
Mock ERP :phase3a, after phase2, 6d
|
|
|
|
|
|
Comparateur de prix :phase3b, after phase2, 5d
|
|
|
|
|
|
Client lourd stocks :phase3c, after phase3a, 8d
|
|
|
|
|
|
Dashboard Analytics :phase3d, after phase3b, 4d
|
|
|
|
|
|
Stripe intégration :phase3e, after phase3c, 4d
|
|
|
|
|
|
Chat temps réel :phase3f, after phase3d, 3d
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**Décision** : Phase 1 uniquement pour ce projet (2 semaines).
|
|
|
|
|
|
Phases 2-3 documentées pour référence future.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔄 Prochaines Étapes
|
|
|
|
|
|
|
|
|
|
|
|
Après complétion de l'application Legacy (Semaine 4) :
|
|
|
|
|
|
|
|
|
|
|
|
1. **Semaine 5** : Démarrage Application Moderne (Setup Next.js + Supabase)
|
|
|
|
|
|
2. **Semaine 6** : Auth Service (Clean Architecture)
|
|
|
|
|
|
3. **Semaine 7-8** : Catalogue & Inventory Services
|
|
|
|
|
|
4. **Semaine 9** : Reservation & Payment Services
|
|
|
|
|
|
5. **Semaine 10** : Comparaison et Présentation
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**Dernière mise à jour** : Octobre 2025
|
|
|
|
|
|
**Prochaine révision** : Fin Semaine 4
|
|
|
|
|
|
**Statut** : 🔵 En cours de planification
|