266 lines
11 KiB
Markdown
266 lines
11 KiB
Markdown
# Plan d'Implémentation — Budget Tracker
|
|
|
|
**Feature** : `003-budget-tracker-core`
|
|
**Date** : 2026-03-15
|
|
**Durée estimée** : 13 jours de travail
|
|
**Stack** : FastAPI + SQLAlchemy 2.0 async + Alembic / React 18 + Vite + Tailwind + Recharts / PostgreSQL 16 / Docker Compose
|
|
|
|
---
|
|
|
|
## Vérification Constitution
|
|
|
|
| Principe | Conformité | Notes |
|
|
|----------|-----------|-------|
|
|
| I. API-First | ✅ | Endpoints définis dans `contracts/api.md`, Pydantic pour la validation |
|
|
| II. Data Integrity | ✅ | Montants en centimes (int), soft-delete, transactions ACID |
|
|
| III. Test Coverage | ✅ | pytest backend, Vitest frontend, ≥80% logique métier |
|
|
| IV. Simplicity | ✅ | Monolithe, pas de microservices, librairies standard |
|
|
| V. Docker-First | ✅ | docker-compose.yml, migrations auto au démarrage, build statique nginx |
|
|
|
|
---
|
|
|
|
## Phase 0 — Setup & Infrastructure (1 jour)
|
|
|
|
### Objectif
|
|
Disposer d'un environnement de développement fonctionnel avec hot-reload.
|
|
|
|
### Tâches
|
|
|
|
1. **Init repo Git** : `.gitignore`, `README.md`, structure dossiers (`backend/`, `frontend/`, `docker/`)
|
|
2. **Docker Compose dev** :
|
|
- Service `db` : PostgreSQL 16, volume persistant, init script
|
|
- Service `backend` : Python 3.12, hot-reload uvicorn, montage code source
|
|
- Service `frontend` : Node 22, Vite dev server, montage code source
|
|
3. **Backend scaffold** :
|
|
- FastAPI app factory (`backend/app/main.py`)
|
|
- Config via Pydantic Settings (`.env` → `backend/app/config.py`)
|
|
- SQLAlchemy 2.0 async engine + session factory
|
|
- Alembic init (`backend/alembic/`)
|
|
- Ruff config (`pyproject.toml`)
|
|
- `requirements.txt` avec versions pinned
|
|
4. **Frontend scaffold** :
|
|
- `npm create vite@latest` avec template React + TypeScript
|
|
- Tailwind CSS setup
|
|
- Prettier config
|
|
- Structure dossiers (`src/components/`, `src/pages/`, `src/api/`, `src/hooks/`)
|
|
5. **`.env.example`** avec toutes les variables documentées
|
|
6. **Smoke test** : `docker compose up` → backend répond `GET /health`, frontend affiche une page
|
|
|
|
### Livrables
|
|
- `docker-compose.yml` + `docker-compose.override.yml` (dev)
|
|
- Backend qui démarre, frontend qui affiche, PostgreSQL qui tourne
|
|
- Premier commit : `chore: initial project setup`
|
|
|
|
### Critères de validation
|
|
- [ ] `docker compose up` fonctionne sans erreur
|
|
- [ ] `GET /health` retourne `{"status": "ok"}`
|
|
- [ ] Frontend accessible sur `localhost:5173`
|
|
- [ ] Ruff et Prettier passent sans erreur
|
|
|
|
---
|
|
|
|
## Phase 1 — Backend Core (3 jours)
|
|
|
|
### Objectif
|
|
API REST fonctionnelle avec auth, transactions et catégories.
|
|
|
|
### Jour 1 : Modèles & Auth
|
|
|
|
1. **Modèles SQLAlchemy** : `User`, `Category`, `Transaction`, `Budget`, `RefreshToken`
|
|
- UUIDs, `created_at`/`updated_at` auto, `deleted_at` pour soft-delete
|
|
- `amount_cents` INTEGER, contrainte CHECK > 0
|
|
2. **Migrations Alembic** : `alembic revision --autogenerate -m "initial models"`
|
|
3. **Auth JWT** :
|
|
- Endpoint `POST /auth/register` (hash bcrypt, validation email unique)
|
|
- Endpoint `POST /auth/login` (access token 15min + refresh token 7j)
|
|
- Endpoint `POST /auth/refresh`
|
|
- Endpoint `POST /auth/logout` (invalidation refresh token)
|
|
- Middleware `get_current_user` pour les routes protégées
|
|
4. **Seed catégories par défaut** : Alimentation, Transport, Logement, Santé, Loisirs, Divers (dépenses) + Salaire, Freelance, Remboursement (revenus)
|
|
|
|
### Jour 2 : CRUD Transactions & Catégories
|
|
|
|
1. **Transactions** :
|
|
- `GET /transactions` : pagination, filtres (mois, catégorie, type), tri par date desc
|
|
- `POST /transactions` : validation Pydantic, isolation par user_id
|
|
- `PUT /transactions/{id}` : vérification ownership
|
|
- `DELETE /transactions/{id}` : soft-delete (set `deleted_at`)
|
|
2. **Catégories** :
|
|
- `GET /categories` : catégories user + catégories système (`is_default`)
|
|
- `POST /categories` : personnalisées uniquement
|
|
- `PUT /categories/{id}` : pas de modif des catégories système
|
|
- `DELETE /categories/{id}` : refus 409 si transactions liées actives
|
|
3. **Services layer** : séparer la logique métier des routes (pas de requêtes SQL dans les endpoints)
|
|
|
|
### Jour 3 : Tests Backend
|
|
|
|
1. **Fixtures pytest** : base de test PostgreSQL (ou SQLite async pour la vitesse), factory pour User/Transaction/Category
|
|
2. **Tests unitaires** :
|
|
- Calcul de solde (revenu - dépense, centimes)
|
|
- Soft-delete : la transaction n'apparaît plus mais existe en base
|
|
- Validation montant > 0, date pas dans le futur (si décidé)
|
|
3. **Tests d'intégration** :
|
|
- Auth : register → login → token valide → accès protégé
|
|
- CRUD transactions : create → list → update → delete → list vérifie absence
|
|
- Filtrage par mois et catégorie
|
|
- Isolation multi-user : user A ne voit pas les transactions de user B
|
|
4. **CI** : `pytest --cov=app/services --cov-fail-under=80`
|
|
|
|
### Livrables
|
|
- API complète (auth + transactions + catégories)
|
|
- Suite de tests avec coverage ≥80% services
|
|
- Documentation OpenAPI auto (`/docs`)
|
|
|
|
---
|
|
|
|
## Phase 2 — Frontend Core (3 jours)
|
|
|
|
### Objectif
|
|
SPA React fonctionnelle avec auth et gestion des transactions.
|
|
|
|
### Jour 4 : Auth & Layout
|
|
|
|
1. **Client API** : module `src/api/client.ts` avec intercepteur Axios/fetch, gestion auto du refresh token
|
|
2. **Auth store** : Context React ou Zustand léger (user, tokens, login/logout)
|
|
3. **Pages auth** : Login, Register avec validation côté client
|
|
4. **Layout principal** : Sidebar navigation (Dashboard, Transactions, Budgets, Historique), header avec nom user + logout
|
|
5. **Route guard** : redirect vers login si non authentifié
|
|
|
|
### Jour 5 : Liste & Formulaire Transactions
|
|
|
|
1. **Page Transactions** :
|
|
- Tableau avec colonnes : date, description, catégorie (badge couleur), montant, type (icône revenu/dépense)
|
|
- Pagination
|
|
- Filtres : mois (date picker), catégorie (select), type (toggle)
|
|
- Bouton supprimer avec confirmation
|
|
2. **Formulaire Transaction** (modal ou page) :
|
|
- Champs : montant (€, converti en centimes), date, type (toggle revenu/dépense), catégorie (select), description
|
|
- Validation temps réel
|
|
- Mode création et édition
|
|
3. **TanStack Query** : cache serveur, invalidation après mutation
|
|
|
|
### Jour 6 : Catégories & Polish
|
|
|
|
1. **Gestion catégories** : page settings ou modal, CRUD catégories personnalisées avec couleur et icône
|
|
2. **Feedback UI** : toasts de confirmation (ajout, suppression), skeleton loading, états vides
|
|
3. **Responsive** : mobile-first, sidebar collapsible sur mobile
|
|
4. **Tests Vitest** : composants critiques (formulaire transaction, affichage montant centimes→euros)
|
|
|
|
### Livrables
|
|
- SPA complète : auth + transactions + catégories
|
|
- Responsive mobile/desktop
|
|
- Tests composants critiques
|
|
|
|
---
|
|
|
|
## Phase 3 — Features Avancées (4 jours)
|
|
|
|
### Jour 7 : Dashboard & Graphiques
|
|
|
|
1. **Endpoints backend** :
|
|
- `GET /dashboard?month=YYYY-MM` : solde, totaux, répartition par catégorie, tendance 6 mois, alertes budget
|
|
2. **Page Dashboard** :
|
|
- Cards KPI : solde courant, revenus du mois, dépenses du mois, solde net
|
|
- Graphique camembert : répartition dépenses par catégorie (Recharts PieChart)
|
|
- Graphique barres : tendance revenus/dépenses sur 6 mois (Recharts BarChart)
|
|
- Alertes budgets dépassés (badges warning/danger)
|
|
3. **Navigation mensuelle** : boutons mois précédent/suivant sur le dashboard
|
|
|
|
### Jour 8 : Budgets (Enveloppes)
|
|
|
|
1. **Endpoints backend** :
|
|
- `GET /budgets?month=YYYY-MM` : budgets avec calcul `spent_cents` et `remaining_cents`
|
|
- `POST /budgets` : création avec contrainte unicité (user, category, month)
|
|
- `PUT /budgets/{id}`, `DELETE /budgets/{id}`
|
|
2. **Page Budgets** :
|
|
- Liste des enveloppes du mois avec barre de progression (vert/orange/rouge)
|
|
- Formulaire ajout/édition budget (catégorie, limite en €)
|
|
- Copie des budgets du mois précédent (bouton "Reconduire")
|
|
3. **Tests** : calcul consommation budget, reconduction, alertes seuil
|
|
|
|
### Jour 9 : Historique Mensuel
|
|
|
|
1. **Endpoint backend** : `GET /history?year=YYYY` → résumé par mois
|
|
2. **Page Historique** :
|
|
- Tableau annuel : mois, revenus, dépenses, solde, nb transactions
|
|
- Clic sur un mois → redirige vers Dashboard du mois sélectionné
|
|
- Sélecteur d'année
|
|
3. **Graphique annuel** : courbe revenus/dépenses sur 12 mois (Recharts LineChart)
|
|
|
|
### Jour 10 : Export CSV & PDF
|
|
|
|
1. **Endpoint CSV** : `GET /export/csv?month=YYYY-MM` → streaming CSV avec headers
|
|
2. **Endpoint PDF** : `GET /export/pdf?month=YYYY-MM` → WeasyPrint, template Jinja2 rapport mensuel
|
|
- En-tête avec titre + mois + date d'export
|
|
- Tableau des transactions
|
|
- Résumé par catégorie
|
|
- Solde
|
|
3. **Boutons export** dans la page Transactions et le Dashboard
|
|
4. **Tests** : validité CSV (parsable), PDF non vide
|
|
|
|
### Livrables
|
|
- Dashboard avec graphiques interactifs
|
|
- Budgets enveloppes avec alertes
|
|
- Historique annuel navigable
|
|
- Export CSV + PDF fonctionnels
|
|
|
|
---
|
|
|
|
## Phase 4 — Finalisation & Production (2 jours)
|
|
|
|
### Jour 11 : Docker Production
|
|
|
|
1. **Dockerfile backend** : multi-stage (build deps → runtime slim)
|
|
2. **Dockerfile frontend** : multi-stage (build Vite → nginx:alpine)
|
|
3. **docker-compose.prod.yml** :
|
|
- Backend : gunicorn + uvicorn workers
|
|
- Frontend : nginx avec compression gzip, cache headers
|
|
- PostgreSQL avec backup volume
|
|
- Health checks sur tous les services
|
|
4. **Entrypoint backend** : exécute `alembic upgrade head` au démarrage
|
|
5. **Sécurité** : CORS restrictif, rate limiting (slowapi), HTTPS-ready headers
|
|
|
|
### Jour 12 : Documentation & Qualité
|
|
|
|
1. **README.md** complet :
|
|
- Description du projet
|
|
- Prérequis (Docker, Docker Compose)
|
|
- Quick start : `cp .env.example .env && docker compose up`
|
|
- Architecture (schéma simplifié)
|
|
- Endpoints API (lien vers `/docs`)
|
|
2. **OpenAPI** : vérifier que la doc auto est complète et lisible
|
|
3. **Tests e2e légers** : script Bash qui lance le stack, crée un user, ajoute une transaction, vérifie le dashboard
|
|
4. **Cleanup** : supprimer code mort, vérifier tous les TODO, linting final
|
|
|
|
### Livrables
|
|
- Docker Compose production-ready
|
|
- README complet
|
|
- Suite complète de tests (unit + integ + e2e)
|
|
- Projet prêt à déployer
|
|
|
|
---
|
|
|
|
## Artefacts générés
|
|
|
|
| Fichier | Description |
|
|
|---------|-------------|
|
|
| `spec.md` | Spécification fonctionnelle (7 user stories, 20 exigences) |
|
|
| `research.md` | Décisions techniques avec rationale |
|
|
| `data-model.md` | 5 entités, index, contraintes |
|
|
| `contracts/api.md` | Contrats API REST (21 endpoints) |
|
|
| `plan.md` | Ce plan d'implémentation |
|
|
|
|
## Risques identifiés
|
|
|
|
| Risque | Impact | Mitigation |
|
|
|--------|--------|-----------|
|
|
| WeasyPrint lourd en Docker | Image backend volumineuse | Multi-stage build, layer caching |
|
|
| Performances dashboard sur gros volume | Requêtes lentes >10k transactions | Index dédiés (voir `data-model.md`), pagination |
|
|
| Complexité auth JWT refresh | Bugs de déconnexion intempestive | Tests d'intégration auth exhaustifs |
|
|
| Recharts bundle size | Frontend lourd | Tree-shaking Vite, lazy loading des pages graphiques |
|
|
|
|
## Prochaines étapes
|
|
|
|
1. **`/speckit.tasks`** — Découper ce plan en tâches atomiques assignables
|
|
2. **`/speckit.implement`** — Lancer l'implémentation phase par phase
|