Fix 20+ defects found by real Docker/PostgreSQL deployment
Première exécution réelle de la stack (build des images, PostgreSQL 16, parcours fonctionnels en HTTP) : 28 tables, 105 index, extension pg_trgm, et 181 assertions rejouées après correction. Santé : filtres enum invalides renvoyaient 500 au lieu d'une erreur française ; plan_line s'arrêtait à la fin de la fenêtre du graphique au lieu de la date d'atteinte de l'objectif ; deficit_target_kcal était recalculé après le plancher calorique ; « dernière pesée » affichait deux valeurs différentes selon l'endpoint ; objectif protéines absent. Vape : durée de vie moyenne des résistances incluait la résistance en cours ; archiver la recette active la laissait active ; coût théorique inventé avant la date d'arrêt ; économies projetées dans le futur ; €/ml arrondi à 2 décimales écrasait le modèle de coût DIY. Finances : le sankey compensait crédits et débits non catégorisés ; rows_total excluait les lignes filtrées, faussant l'arithmétique du rapport d'import. Socle : les erreurs HTTP du framework fuitaient en anglais dans l'enveloppe française ; nginx renvoyait sa page 413 HTML au lieu du JSON français ; fins de ligne normalisées en LF. 348 tests pytest (+7), ruff, tsc et vite build au vert. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -127,8 +127,9 @@ Détails utiles :
|
||||
|
||||
### Imports et connecteurs (`/imports`)
|
||||
|
||||
- Assistant en trois étapes : **Fichier → Vérification → Import**, avec détection
|
||||
automatique du format à partir de l'en-tête du fichier.
|
||||
- Assistant en trois étapes : **Fichier → Vérification → Import**. Le format est détecté à
|
||||
partir de l'en-tête du fichier ; pour un relevé bancaire, le profil de banque est
|
||||
présélectionné à partir de ce format et reste modifiable avant l'aperçu.
|
||||
- Éditeur de mappage de colonnes (séparateur, encodage, format de date, colonnes) enregistré
|
||||
dans un profil personnel.
|
||||
- **Formats reconnus** : relevé bancaire CSV, relevé bancaire OFX, PayPal CSV,
|
||||
@@ -150,14 +151,12 @@ révocation de clés d'API par appareil), **Application** (préférences locales
|
||||
|
||||
**Il n'y en a pas, et ce n'est pas un oubli.**
|
||||
|
||||
L'application a été développée et testée intégralement hors ligne : la suite de tests
|
||||
backend et la compilation du frontend passent, mais **la pile Docker Compose n'a jamais été
|
||||
démarrée** (le démon Docker était indisponible pendant tout le développement). Aucune
|
||||
capture n'a donc pu être prise sur une instance réelle.
|
||||
|
||||
Plutôt que de publier des images de synthèse trompeuses, cette section restera vide jusqu'à
|
||||
votre premier démarrage. Une fois l'application lancée, les pages à capturer en priorité
|
||||
sont : le tableau de bord, `/sante/poids`, `/vape/economies` et `/finances`.
|
||||
La pile a bien été construite et exécutée (voir « Ce qui est vérifié » ci-dessous), mais la
|
||||
validation s'est faite **en HTTP, pas dans un navigateur** : aucune session graphique n'a
|
||||
été ouverte, donc aucune capture authentique n'a pu être prise. Plutôt que de publier des
|
||||
images de synthèse trompeuses, cette section restera vide jusqu'à votre premier démarrage.
|
||||
Les pages à capturer en priorité : le tableau de bord, `/sante/poids`, `/vape/economies` et
|
||||
`/finances`.
|
||||
|
||||
---
|
||||
|
||||
@@ -165,18 +164,32 @@ sont : le tableau de bord, `/sante/poids`, `/vape/economies` et `/finances`.
|
||||
|
||||
### Prérequis
|
||||
|
||||
- **Docker Desktop installé ET démarré.** Vérifiez que la baleine est bien active dans la
|
||||
barre des tâches ; `docker compose version` doit répondre sans erreur.
|
||||
- **Docker installé et démarré** ; `docker compose version` doit répondre sans erreur
|
||||
(Compose v2 ou plus récent). Sous Windows, vérifiez que Docker Desktop est bien actif.
|
||||
- Environ 2 Go d'espace disque pour les images et la base.
|
||||
- Aucun autre service n'écoute sur le port choisi (80 par défaut).
|
||||
- Aucun autre service n'écoute sur les ports choisis (80 et 8000 par défaut).
|
||||
|
||||
> ⚠️ **À lire avant le premier lancement.** Le démon Docker était **hors service pendant
|
||||
> toute la phase de développement** : la pile Compose n'a donc jamais été construite ni
|
||||
> démarrée. Le code applicatif, lui, est validé (292 tests backend, compilation frontend).
|
||||
> Attendez-vous éventuellement à un petit ajustement lors du tout premier `up` — le plus
|
||||
> probable étant un temps de build long, ou une image de base à retélécharger. Si un
|
||||
> conteneur refuse de démarrer, consultez ses journaux avec
|
||||
> `docker compose logs api` avant toute autre chose.
|
||||
### Ce qui est vérifié
|
||||
|
||||
La séquence ci-dessous a été **exécutée telle quelle** sur un hôte Ubuntu (Docker Compose
|
||||
v5.1.1, 8 vCPU, 1,8 Go de RAM), à partir d'un volume de données vide :
|
||||
|
||||
- les deux images se construisent (`lifetrack-api` ≈ 330 Mo, `lifetrack-web` ≈ 76 Mo) ;
|
||||
- les trois conteneurs passent `healthy` en une vingtaine de secondes ;
|
||||
- le schéma est créé sur un **vrai PostgreSQL 16** (28 tables, 105 index, extension
|
||||
`pg_trgm` activée) et les données survivent à un `down` / `up` ;
|
||||
- l'assistant de premier démarrage, puis un parcours par module (pesée + checklist du jour,
|
||||
réglages vape + recharge + économies cumulées, import d'un relevé bancaire CSV en cp1252
|
||||
avec ré-import dédupliqué et annulation) ont été rejoués **en HTTP à travers nginx** :
|
||||
SPA, liens profonds, proxy `/api/` et gros fichiers compris.
|
||||
|
||||
Ce qui n'a **pas** été vérifié : le rendu graphique dans un navigateur (voir « Captures
|
||||
d'écran »). Si un conteneur refuse de démarrer, commencez par
|
||||
`docker compose logs api`.
|
||||
|
||||
> **Hôte avec moins de 2 Go de RAM** : construisez les images **une par une** (étape 3
|
||||
> ci-dessous) et, si `vite build` se fait tuer par l'OOM killer, décommentez
|
||||
> `NODE_OPTIONS=--max-old-space-size=1024` dans `.env`.
|
||||
|
||||
### 1. Créer le fichier `.env`
|
||||
|
||||
@@ -229,39 +242,59 @@ Deux variables restent commentées et ne servent qu'au développement :
|
||||
> `LIFETRACK_DATABASE_URL` n'est **pas** à renseigner dans `.env` : `docker-compose.yml` la
|
||||
> compose automatiquement à partir de `POSTGRES_USER`, `POSTGRES_PASSWORD` et `POSTGRES_DB`.
|
||||
|
||||
### 3. Lancer la pile
|
||||
### 3. Construire les images
|
||||
|
||||
C'est la séquence exacte qui a été validée. Les deux builds sont **séparés** : le build web
|
||||
(`npm ci` + `vite build`) est le seul gros consommateur de mémoire, mieux vaut ne pas le
|
||||
faire tourner en même temps qu'autre chose.
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose build api # ~30 s
|
||||
docker compose build web # ~40 s
|
||||
```
|
||||
|
||||
`docker compose build` (sans argument) fonctionne aussi et construit les deux à la suite.
|
||||
|
||||
### 4. Lancer la pile
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Trois conteneurs démarrent : `postgres` (base de données), `api` (FastAPI) et `web`
|
||||
(nginx servant le frontend compilé et relayant `/api/` vers l'API). Le premier build prend
|
||||
plusieurs minutes.
|
||||
(nginx servant le frontend compilé et relayant `/api/` vers l'API). Depuis un volume vide,
|
||||
il faut une vingtaine de secondes pour que les trois soient `healthy`.
|
||||
|
||||
Suivre le démarrage :
|
||||
Vérifier :
|
||||
|
||||
```bash
|
||||
docker compose logs -f
|
||||
docker compose ps # attendre (healthy) sur postgres, api et web
|
||||
docker compose logs -f # au besoin, suivre le démarrage
|
||||
```
|
||||
|
||||
### 4. Ouvrir l'application
|
||||
### 5. Ouvrir l'application
|
||||
|
||||
<http://localhost>
|
||||
|
||||
Si vous avez changé `WEB_PORT`, adaptez l'adresse (par exemple `http://localhost:8080`).
|
||||
Depuis un autre appareil du réseau local, utilisez l'adresse IP du serveur.
|
||||
Depuis un autre appareil du réseau local, utilisez l'adresse IP du serveur. L'assistant de
|
||||
premier démarrage s'ouvre automatiquement et crée le compte administrateur.
|
||||
|
||||
Deux adresses utiles :
|
||||
|
||||
- <http://localhost/api/healthz> — doit répondre `{"status":"ok"}`
|
||||
- <http://localhost/api/docs> — documentation interactive de l'API
|
||||
|
||||
> `docker-compose.yml` porte `name: lifetrack` : toutes les commandes ci-dessus sont donc
|
||||
> déjà rattachées au projet `lifetrack`, sans avoir à passer `-p`.
|
||||
|
||||
### Arrêter, mettre à jour, repartir de zéro
|
||||
|
||||
```bash
|
||||
docker compose down # arrêt, les données sont conservées
|
||||
docker compose up -d --build # reconstruction après mise à jour du code
|
||||
docker compose build api # après mise à jour du code…
|
||||
docker compose build web
|
||||
docker compose up -d # …puis redémarrage
|
||||
docker compose down -v # ⚠️ supprime AUSSI le volume : toutes vos données
|
||||
```
|
||||
|
||||
@@ -317,7 +350,7 @@ L'environnement virtuel Python est déjà présent dans `apps/api/.venv`.
|
||||
```bash
|
||||
cd apps/api
|
||||
|
||||
# Suite de tests — 292 tests, exécutés sur SQLite en mémoire
|
||||
# Suite de tests — 348 tests, exécutés sur SQLite en mémoire
|
||||
.venv/Scripts/python.exe -m pytest
|
||||
|
||||
# Lint et formatage
|
||||
@@ -341,7 +374,9 @@ python -m venv .venv
|
||||
|
||||
> Les tests tournent sur **SQLite en mémoire** alors que la production utilise
|
||||
> **PostgreSQL 16** : tous les types de colonnes doivent rester portables (voir
|
||||
> [CONVENTIONS.md](CONVENTIONS.md) §C8).
|
||||
> [CONVENTIONS.md](CONVENTIONS.md) §C8). `app/tests/test_postgres_ddl.py` vérifie hors
|
||||
> ligne le DDL réellement émis pour PostgreSQL (types natifs, index partiels, cascades
|
||||
> d'import) ; ce DDL a par ailleurs été confronté à un vrai serveur PostgreSQL 16.
|
||||
|
||||
### Frontend (React + Vite)
|
||||
|
||||
@@ -388,7 +423,7 @@ LifeTrack/
|
||||
│ │ │ ├─ core/ # config, base, sécurité, pagination, erreurs,
|
||||
│ │ │ │ # framework d'import et d'ingestion, chargeur de modules
|
||||
│ │ │ ├─ modules/ # auth, health, vape, finance, imports
|
||||
│ │ │ ├─ tests/ # 292 tests pytest
|
||||
│ │ │ ├─ tests/ # 348 tests pytest
|
||||
│ │ │ └─ main.py # création de l'app — ne jamais modifier pour un module
|
||||
│ │ ├─ requirements.txt
|
||||
│ │ └─ openapi.json # schéma OpenAPI exporté
|
||||
@@ -478,7 +513,7 @@ utilisateur.
|
||||
| Base de données | PostgreSQL 16 (pilote psycopg 3) — SQLite en mémoire pour les tests |
|
||||
| Frontend | React 18 · TypeScript strict · Vite 6 · TailwindCSS · Apache ECharts · TanStack Query · React Router |
|
||||
| Déploiement | Docker Compose : `postgres` + `api` + `web` (nginx 1.27) |
|
||||
| Qualité | pytest (292 tests) · ruff · `tsc --noEmit` |
|
||||
| Qualité | pytest (348 tests) · ruff · `tsc --noEmit` |
|
||||
|
||||
Aucune ressource externe n'est chargée à l'exécution : polices, icônes et bibliothèques sont
|
||||
embarquées dans le build.
|
||||
|
||||
Reference in New Issue
Block a user