# Guide d'utilisation de LifeTrack Ce guide décrit **comment se servir de LifeTrack au quotidien** : brancher ses vraies données, suivre son poids, remplir son journal alimentaire, piloter le sevrage tabagique et importer ses relevés bancaires. Il part du principe que l'application tourne déjà et que votre compte est créé. Sinon, commencez par le [README](../README.md#démarrage-rapide-docker-compose). --- ## Sommaire - [Avant de commencer](#avant-de-commencer) - [Connecter Health Connect](#connecter-health-connect) - [Suivi poids et calories au quotidien](#suivi-poids-et-calories-au-quotidien) - [Nutrition](#nutrition) - [Vape et sevrage tabagique](#vape-et-sevrage-tabagique) - [Finances](#finances) - [Dépannage](#dépannage) --- ## Avant de commencer Trois réglages conditionnent presque tous les calculs. Faites-les une bonne fois pour toutes dans **Réglages** : | Onglet | À renseigner | Ce que ça débloque | |---|---|---| | **Profil** | Taille, sexe, date de naissance, niveau d'activité | Métabolisme de base, dépense estimée, IMC | | **Objectif** | Poids de départ, poids cible, mode de calcul | Budget calorique quotidien, projection, planning | | **Vape** | Date d'arrêt, cigarettes/jour avant, prix du paquet | Économies, jalons santé | Le profil comporte aussi un **fuseau horaire** (`Europe/Paris` par défaut). C'est lui qui détermine à quel jour appartient une donnée horodatée : changez-le si vous vivez ailleurs, sinon laissez-le tranquille. --- ## Connecter Health Connect Health Connect est le magasin de données santé d'Android. Point crucial à comprendre avant tout : **c'est une base de données locale au téléphone. Aucun serveur ne peut aller y chercher quoi que ce soit.** Il n'existe pas d'API cloud, et l'ancienne API Google Fit est morte (inscriptions fermées depuis mai 2024, arrêt en 2026). Les données ne peuvent donc que **partir du téléphone vers LifeTrack**. Trois chemins, du plus automatique au plus manuel. ### Chemin 1 — Envoi automatique vers l'API d'ingestion #### Étape 1 : créer une clé d'appareil 1. Ouvrez **Réglages → Appareils & API**. 2. Cliquez sur **Créer une clé**. 3. Donnez-lui un nom parlant (par exemple « Pixel de Julien »). 4. Cochez la portée **« Santé (pesées, activité, séances) »** — techniquement `ingest:health`. 5. Validez. > ⚠️ **La clé en clair n'est affichée qu'une seule fois.** Copiez-la immédiatement. > LifeTrack n'en conserve qu'une empreinte : personne, pas même vous, ne pourra la > réafficher. Si vous la perdez, révoquez-la et créez-en une autre. > > Une clé ressemble à `ltk_` suivi d'une longue chaîne aléatoire. La liste vous montre ensuite, pour chaque clé, son préfixe, ses portées, sa date de création et sa dernière utilisation — pratique pour vérifier qu'une passerelle envoie bien quelque chose. #### Étape 2 : l'adresse à viser L'endpoint d'ingestion est : ``` POST http:///api/ingest/health ``` L'onglet **Imports → Connecteurs & API** affiche cette URL déjà construite avec l'adresse depuis laquelle vous consultez l'application, avec un bouton **Copier**. Deux choses obligatoires dans la requête : - l'en-tête **`X-API-Key: ltk_…`** avec votre clé d'appareil ; - un corps JSON de la forme suivante : ```json { "source": "health_connect", "records": [ { "type": "steps", "external_id": "uuid-fourni-par-health-connect", "data": { "day": "2026-08-13", "steps": 9421 } }, { "type": "weight", "data": { "measured_at": "2026-08-13T06:42:00Z", "weight_kg": 83.4 } } ] } ``` Vous pouvez tester tout de suite depuis n'importe quelle machine : ```bash curl -X POST http://localhost/api/ingest/health \ -H "X-API-Key: ltk_votre_cle_ici" \ -H "Content-Type: application/json" \ -d '{"source":"health_connect","records":[{"type":"weight","data":{"measured_at":"2026-08-13T06:42:00Z","weight_kg":83.4}}]}' ``` La réponse indique combien d'enregistrements ont été insérés, mis à jour, ignorés comme doublons, et le détail des lignes rejetées. **Un enregistrement invalide ne fait jamais échouer le lot entier.** #### Étape 3 : quelles données passent Huit types d'enregistrements sont acceptés : | `type` | Ce que ça alimente | Champs principaux reconnus | |---|---|---| | `weight` | Pesées | `measured_at` / `time` / `start_time`, `weight_kg`, `body_fat_pct` | | `steps` | Activité quotidienne | `day` ou `start_time`, `steps` / `count` | | `distance` | Activité quotidienne | `distance_m` ou `distance_km` | | `active_calories` | Activité quotidienne | `active_kcal` / `active_calories` | | `total_calories` | Activité quotidienne (TDEE mesuré) | `total_kcal` / `total_calories` | | `exercise_session` | Séances de sport | `start_time`, `end_time` ou `duration_s`, `exercise_type`, `energy_kcal`, `distance_m`, `avg_hr`, `max_hr` | | `nutrition` | Journal alimentaire | `eaten_at`, `energy_kcal`, `name`, `meal_type`, macros | | `hydration` | Hydratation | `drunk_at`, `volume_ml` ou `volume_liters` | Le format des champs est volontairement tolérant : LifeTrack accepte les noms « Health Connect » en `snake_case`, les objets imbriqués `value` et `metadata`, les horodatages ISO 8601 comme les époques Unix en secondes ou millisecondes. Un horodatage sans fuseau est interprété en **Europe/Paris** puis converti en UTC. La charge utile d'origine est toujours conservée dans la ligne créée. Les types de sport connus sont reconnus et traduits (`running`, `walking`, `cycling`, `swimming`, `strength_training`, `hiit`, `yoga`, `hiking`, tapis de course en marche ou en course…) ; le reste atterrit en « Autre » avec le libellé d'origine conservé. #### Étape 4 : la passerelle Android — et ses limites réelles L'application open source de référence est **health-connect-webhook** (, AGPL-3.0, disponible sur le Play Store). Elle lit Health Connect en tâche de fond et POSTe du JSON vers l'URL de votre choix. **Soyons parfaitement clairs : en l'état, elle ne peut pas être branchée directement sur LifeTrack.** Deux obstacles, tous deux réels : 1. **Elle ne sait pas poser d'en-tête HTTP personnalisé.** Sa sécurité repose entièrement sur le secret de l'URL. Or `POST /api/ingest/health` exige `X-API-Key`. Les documents de conception prévoyaient une route acceptant un jeton dans le chemin de l'URL pour ce cas précis — **elle n'a pas été implémentée**. 2. **Son enveloppe JSON n'est pas celle attendue.** Elle envoie un objet contenant `timestamp`, `app_version` et un tableau par type de données. LifeTrack attend `{"source": …, "records": [{"type": …, "data": …}]}`. Le *contenu* de chaque enregistrement est bien compris par LifeTrack ; c'est l'emballage qui diffère. Concrètement, vous avez trois options : - **Intercaler un petit relais** entre le téléphone et LifeTrack (un script, une automatisation Node-RED ou n8n, une fonction sur votre serveur) qui reçoit le webhook, découpe les tableaux en `records` et rejoue la requête avec l'en-tête `X-API-Key`. C'est une trentaine de lignes. - **Utiliser n'importe quelle application capable de poser un en-tête HTTP** (Tasker, HTTP Shortcuts, Macrodroid, ou une future application compagnon) : le format canonique ci-dessus est simple à produire. - **Rester sur l'import CSV** (chemin 2), qui fonctionne aujourd'hui sans aucun bricolage. #### Les autres limites, à connaître avant de s'engager - **Fenêtre de 48 heures.** La passerelle ne relit que les 48 dernières heures. Si votre téléphone reste éteint ou hors ligne plus longtemps, ces journées sont définitivement perdues pour ce canal — d'où l'intérêt de l'export CSV en filet de sécurité. - **Historique limité à 30 jours.** Health Connect n'autorise par défaut la lecture que des 30 jours précédant la première autorisation. Tout ce qui est plus ancien ne viendra **jamais** par ce chemin : il faudra passer par un export de fichiers. - **Installation hors Play Store.** Une application compagnon maison devra être installée manuellement (sideload) : APK signé localement, permissions accordées dans l'écran Health Connect du téléphone. C'est faisable, mais ce n'est pas un simple clic. - **Économiseurs de batterie.** Xiaomi, Huawei, Samsung et consorts tuent volontiers les tâches de fond. Si les envois s'espacent sans raison, excluez l'application de l'optimisation de batterie dans les réglages Android. - **Sécurité réseau.** Une clé d'appareil circule à chaque envoi. N'exposez pas LifeTrack en clair sur Internet : restez sur votre réseau local ou passez par un VPN, sinon mettez du HTTPS devant nginx. ### Chemin 2 — Import CSV avec Health Sync (le plus fiable aujourd'hui) **Health Sync** (, environ 4 € en achat unique, essai d'une semaine) exporte automatiquement vos données Health Connect en CSV vers Google Drive, en tâche de fond, sans intervention. 1. Installez et configurez Health Sync sur le téléphone, avec Health Connect comme source. 2. Activez l'export automatique vers Google Drive (fichiers jour, 7 jours, mois ou 30 jours glissants). 3. Récupérez le CSV sur votre ordinateur. 4. Dans LifeTrack, ouvrez **Imports**, déposez le fichier et laissez la **détection automatique** faire son travail — le profil attendu est **« Health Sync / Health Connect (export CSV) »**. 5. Vérifiez l'aperçu, puis lancez l'import. Ce chemin est aussi **le seul moyen de rattraper un historique profond** (au-delà des 30 jours de Health Connect) et de boucher les trous laissés par la fenêtre de 48 heures. Ré-importer un fichier déjà traité ne crée aucun doublon : allez-y sans crainte. Un profil **« Historique de poids (CSV date/poids) »** existe également pour un simple fichier à deux colonnes date et poids, quelle qu'en soit l'origine. ### Chemin 3 — Saisie manuelle Toujours disponible, et parfois plus rapide qu'on ne croit : - une pesée depuis la carte **Aujourd'hui** du tableau de bord ou depuis **Santé → Poids & Objectif** ; - une séance de sport depuis **Santé → Activité & Sport** ; - un repas depuis **Santé → Nutrition**. C'est le mode de repli recommandé pour les séances de tapis de course : l'application FitShow ne partage ses données ni avec Health Connect, ni avec Google Fit, ni sous forme de fichiers. Ses séances resteront enfermées dans son application tant qu'un enregistrement Bluetooth direct n'aura pas été développé (envisagé en v3). --- ## Suivi poids et calories au quotidien ### Le planning de pesées LifeTrack ne vous demande pas de cocher des cases : **une habitude est considérée comme faite dès qu'une donnée existe pour ce jour-là.** Vous vous pesez, la pesée compte. Vous enregistrez un repas, le journal alimentaire du jour compte. Pour définir votre plan, allez dans **Réglages → Objectif → Planning de suivi** (ou depuis la page **Santé → Poids & Objectif**). Trois habitudes indépendantes : | Habitude | Validée par | |---|---| | **Pesée** | Une pesée enregistrée ce jour-là | | **Séance** | Une séance de sport ce jour-là | | **Journal alimentaire** | Au moins un aliment enregistré ce jour-là | Pour chacune, cochez les jours de la semaine concernés et activez-la. Une pesée quotidienne donne la tendance la plus fiable ; trois fois par semaine suffisent largement. LifeTrack en déduit ensuite : - l'**assiduité** : jours faits ÷ jours planifiés, en pourcentage ; - la **série en cours** et la **meilleure série**, comptées uniquement sur les jours planifiés ; - un **calendrier** à quatre états : fait, manqué, fait hors planning, jour de repos. Détail appréciable : **le jour même ne casse jamais une série tant qu'il n'est pas fini.** Si vous vous pesez habituellement le matin et que vous consultez l'application à midi sans l'avoir fait, votre série reste intacte. ### La carte « Aujourd'hui » En haut du tableau de bord, elle résume l'état du jour : ce qui était prévu, ce qui est fait, et un bouton d'action directe pour chaque manque (**Noter ma pesée**, **Noter ma séance**). C'est le point d'entrée quotidien de l'application. ### La saisie rapide d'une pesée Le bouton **Noter ma pesée** ouvre une modale minimale : le poids, éventuellement la date et l'heure si ce n'est pas maintenant. Deux secondes, et la tendance se recalcule. Une seule règle à connaître : **c'est la première pesée du jour qui alimente la tendance.** Si vous vous pesez trois fois dans la journée, seule celle du matin compte pour la courbe — les autres restent visibles dans l'historique. ### Comprendre les chiffres C'est ici que LifeTrack cesse d'être un carnet et devient un outil. Quatre notions, dans l'ordre où elles s'enchaînent. #### 1. Le métabolisme de base (BMR) C'est ce que votre corps brûle **au repos complet**, juste pour rester en vie. LifeTrack utilise la formule de **Mifflin-St Jeor**, la référence actuelle : ``` BMR = 10 × poids(kg) + 6,25 × taille(cm) − 5 × âge(ans) + correctif ``` Le correctif vaut `+5` pour un homme, `−161` pour une femme, `−78` pour « autre ». *Exemple : un homme de 40 ans, 178 cm, 83 kg → 10 × 83 + 6,25 × 178 − 5 × 40 + 5 = **1 747 kcal/jour**.* C'est ce que vous brûleriez en restant couché toute la journée. #### 2. La dépense énergétique totale (TDEE) C'est le BMR **plus tout le reste** : marcher, travailler, faire du sport, digérer. LifeTrack le calcule chaque jour selon trois méthodes, par ordre de préférence : 1. **Mesuré** — si votre montre ou votre téléphone a envoyé une valeur de calories totales crédible (supérieure à 80 % du BMR), c'est elle qui gagne. C'est la plus juste. 2. **BMR + calories actives** — si vous n'avez que les calories *actives* de la journée, elles s'ajoutent au BMR. 3. **Estimé** — sinon, le BMR est multiplié par le facteur de votre niveau d'activité : | Niveau | Facteur | |---|---| | Sédentaire | × 1,2 | | Légèrement actif | × 1,375 | | Modérément actif | × 1,55 | | Très actif | × 1,725 | | Extrêmement actif | × 1,9 | Le TDEE utilisé pour votre budget est **lissé sur 7 jours** : une journée exceptionnelle ne fait pas bondir votre autorisation calorique du lendemain. #### 3. Les 7 700 kcal par kilo C'est la constante qui relie calories et poids : **perdre 1 kg de masse corporelle correspond à un déficit d'environ 7 700 kcal.** D'où le calcul du budget quotidien : ``` Budget = TDEE lissé − (rythme visé en kg/semaine × 7 700 ⁄ 7) ``` Autrement dit, chaque tranche de **0,1 kg/semaine** que vous visez coûte **110 kcal par jour**. *Exemple : TDEE lissé à 2 500 kcal, objectif 0,5 kg/semaine → déficit de 0,5 × 1 100 = 550 kcal/jour → **budget de 1 950 kcal**.* Un **plancher de sécurité** s'applique : 1 500 kcal pour un homme, 1 200 kcal pour une femme, sauf valeur personnalisée. Si votre objectif passe sous ce plancher, le budget est relevé et l'interface vous avertit que le rythme visé est trop agressif. #### 4. La tendance, pas la balance Votre poids varie de un à deux kilos d'un jour à l'autre pour des raisons qui n'ont rien à voir avec la graisse : sel, hydratation, digestion, cycle hormonal. Se fier au chiffre brut, c'est se condamner à l'angoisse. LifeTrack calcule donc une **moyenne mobile exponentielle** (méthode dite « Hacker's Diet », facteur de lissage 0,1) : chaque nouvelle pesée ne déplace la courbe que de 10 % de l'écart constaté. Les jours sans pesée sont correctement compensés, sans fausser le lissage. **C'est cette courbe de tendance qu'il faut regarder, pas les points.** À partir de trois pesées, LifeTrack calcule aussi une pente par régression linéaire et en déduit la **date d'atteinte estimée** de votre objectif. Trois réponses possibles : - une date, si la pente va dans le bon sens ; - **« objectif atteint »**, à moins de 100 g de la cible ; - **« ne converge pas »**, si la pente est nulle, part dans le mauvais sens, ou donne une échéance à plus de dix ans. Ce n'est pas un bug : c'est une information. #### 5. La calibration adaptative Après **21 jours au moins** de journal alimentaire renseigné, la page **Balance énergétique** compare la perte de poids *prévue* par vos déficits cumulés à la perte *réellement observée* sur la tendance, et en déduit votre **TDEE réel**. C'est la fonction la plus utile de LifeTrack sur la durée : elle corrige d'un coup les erreurs de la formule théorique, la sous-estimation systématique des portions et l'adaptation métabolique. Si l'écart est important, un bouton vous propose d'adopter cette valeur mesurée. --- ## Nutrition ### Recherche d'aliments avec Open Food Facts Dans **Santé → Nutrition**, le champ de recherche interroge, dans cet ordre : 1. **le cache local** de LifeTrack — tous les aliments déjà consultés ; 2. **Open Food Facts**, la base collaborative mondiale (plus de 3 millions de produits, très bonne couverture des rayons français). Tapez au moins **2 caractères**. La recherche est en français et passe par le serveur, jamais par votre navigateur. **Chaque produit consulté est mis en cache définitivement.** Un produit que vous mangez souvent n'est téléchargé qu'une seule fois, puis répond instantanément, même hors ligne. Vous pouvez aussi chercher par **code-barres**. Les valeurs sont mémorisées pour 100 g : calories, protéines, glucides, sucres, lipides, acides gras saturés, fibres, sel. Quand les calories manquent mais que les kilojoules sont présents, la conversion est faite automatiquement (÷ 4,184). > **Open Food Facts est collaboratif : les données ne sont pas garanties.** Un produit peut > avoir des valeurs fantaisistes ou une portion mal renseignée. Un coup d'œil au chiffre > avant de valider évite bien des surprises. Si la base est injoignable, LifeTrack vous le > dit clairement et vous propose la saisie manuelle. > Pas de base d'aliments génériques française à ce jour. La table CIQUAL de l'ANSES > (« Pomme, crue », « Baguette courante »…) était prévue mais **n'a pas été intégrée**. Pour > vos plats maison, saisissez les valeurs à la main — ou créez-vous un favori une bonne fois > pour toutes. ### Favoris et aliments récents Deux raccourcis qui font toute la différence sur la durée : - **Favoris** — vos aliments et portions habituels, épinglés en tête de liste. Votre café du matin, votre yaourt, votre portion de riz. - **Récents** — les derniers aliments enregistrés, proposés automatiquement. Le journal est organisé par repas : petit-déjeuner, déjeuner, dîner, collation. Une entrée sans type de repas explicite est classée selon l'heure (avant 11 h, petit-déjeuner ; avant 15 h, déjeuner ; avant 18 h, collation ; ensuite, dîner). L'**hydratation** se suit à part, avec un objectif quotidien réglable dans le profil (2 000 ml par défaut). ### Importer son historique Foodvisor Foodvisor **n'expose aucune API** : ni OAuth, ni webhook, ni endpoint « mes repas ». Aucune synchronisation continue n'est possible. Le seul chemin est un **export ponctuel**, à faire une fois pour rapatrier votre historique. #### Étape 1 : demander l'export dans l'application Dans Foodvisor : **Réglages → Compte → « Demander mes données »** (l'intitulé et l'emplacement varient selon les versions ; sur le tableau de bord web, cherchez sous `Account → Privacy → Data`). L'export arrive **par e-mail**, généralement sous 24 à 72 heures. #### Étape 2 : si l'option est absente ou l'export incomplet, invoquez le RGPD Foodvisor est une société française : vous disposez du **droit d'accès (article 15)** et du **droit à la portabilité (article 20)**. Écrivez à **`data@foodvisor.io`**. Modèle : > Objet : Demande d'accès et de portabilité de mes données personnelles (RGPD) > > Bonjour, > > Titulaire d'un compte Foodvisor associé à l'adresse ``, je souhaite exercer > mes droits d'accès (article 15 du RGPD) et de portabilité (article 20). > > Je vous demande de me transmettre **l'intégralité de mon journal alimentaire dans un format > structuré, couramment utilisé et lisible par machine (CSV ou JSON)**, incluant pour chaque > entrée : l'horodatage, le type de repas, le nom de l'aliment, la portion et les valeurs > nutritionnelles (calories et macronutriments). Merci d'y joindre également mon historique > de poids et mes objectifs. > > Le délai légal de réponse est d'un mois à compter de la réception de la présente. > > Cordialement, > `` Le délai légal est d'**un mois**, prolongeable de deux mois pour une demande complexe. #### Étape 3 : importer dans LifeTrack 1. Ouvrez **Imports**. 2. Déposez le CSV du journal alimentaire (si vous avez reçu une archive ZIP, extrayez-la d'abord : c'est le fichier contenant une ligne par aliment consommé qui nous intéresse). 3. Laissez la détection automatique, ou choisissez le profil **« Foodvisor (export CSV) »**. 4. Vérifiez l'aperçu, puis lancez l'import. L'importeur est volontairement tolérant : il accepte les en-têtes en français comme en anglais, les séparateurs `,` et `;`, les encodages UTF-8 et Windows-1252, la virgule décimale. Chaque ligne doit au minimum comporter **une date, un nom d'aliment et des calories** — les autres colonnes sont facultatives. Ce que l'export Foodvisor **ne contient pas**, et que vous ne récupérerez donc jamais : les photos, les scores de confiance de l'IA, les codes-barres scannés, les micronutriments au-delà des macros, et la décomposition des recettes en ingrédients. --- ## Vape et sevrage tabagique ### Étape 1 : la référence tabac Rien ne fonctionne sans elle. **Réglages → Vape** : | Champ | Exemple | Rôle | |---|---|---| | **Date d'arrêt du tabac** | 12/03/2026 | Point de départ des économies et des jalons santé | | **Cigarettes par jour** | 20 | Votre consommation **avant** l'arrêt | | **Cigarettes par paquet** | 20 | Généralement 20 | | **Prix du paquet** | 12,50 € | Prix **actuel** du paquet | | **Taux de nicotine par défaut** | 6 mg/ml | Utilisé quand une recharge n'en précise pas | Cette référence est **gelée** : elle représente ce que vous dépenseriez si vous n'aviez pas arrêté. Elle n'est jamais recalculée à partir de vos données de vape. > **Une nuance d'honnêteté que LifeTrack affiche lui-même :** le prix retenu est le prix > d'aujourd'hui, pas celui du jour de votre arrêt. Comme le tabac augmente régulièrement, les > économies affichées sur les périodes anciennes sont **légèrement optimistes**. C'est > assumé, et c'est indiqué dans l'interface. Tant que ce formulaire n'est pas rempli, le module vape affiche « Module vape non configuré » et refuse de calculer quoi que ce soit — c'est normal. ### Étape 2 : saisir les recharges Onglet **Consommation**, bouton d'ajout. Deux façons de déclarer : - **Recharge** (`refill`) — le remplissage habituel : la date et le volume en ml. Plusieurs recharges dans la journée s'additionnent. - **Total du jour** (`daily_total`) — vous n'avez pas compté vos remplissages mais vous savez que vous avez consommé 6 ml aujourd'hui. **Cette valeur remplace la somme des recharges du jour**, elle ne s'y ajoute pas. Vous pouvez préciser le taux de nicotine et la recette utilisée ; sinon les valeurs par défaut s'appliquent. Une journée sans aucune saisie n'est **pas** comptée comme zéro : elle est marquée « non suivie ». Les moyennes ne portent que sur les jours réellement suivis, et l'interface affiche la proportion de jours suivis pour que vous sachiez quelle confiance accorder aux chiffres. ### Étape 3 : changer une résistance en un clic Onglet **Résistances**. Un seul bouton : **la date et l'heure sont celles de maintenant**, sans aucune saisie. C'est la fonction la plus utilisée du module, elle devait être instantanée. LifeTrack en déduit : - la **durée de vie** de la résistance précédente, affichée immédiatement après le clic ; - la **durée de vie moyenne**, calculée sur les **5 derniers cycles** (14 jours tant qu'il n'y a pas au moins deux changements) ; - le **volume d'e-liquide passé** dans chaque résistance ; - l'**âge de la résistance en cours**. Vous pouvez rattacher un produit du catalogue au changement pour que son prix entre dans le calcul d'amortissement. ### Étape 4 : le modèle de coût DIY Onglet **Coûts & modèle**. Deux niveaux, selon votre patience. **Le catalogue de produits.** Chaque produit porte un prix et une contenance : base (1 000 ml), booster nicotine (10 ml), arôme (30 ml), résistances (paquet de 5). C'est tout ce dont LifeTrack a besoin. **Les recettes.** Une recette déclare un volume total, un taux de nicotine visé et ses composants. Le coût se calcule simplement : ``` coût d'un composant = quantité × (prix du flacon ⁄ contenance du flacon) coût au ml = somme des composants ⁄ volume total ``` *Exemple pour 100 ml : 20 ml de booster à 1 € les 10 ml (2,00 €) + 10 ml d'arôme à 6 € les 30 ml (2,00 €) + 70 ml de base à 12 € le litre (0,84 €) = **4,84 € pour 100 ml, soit 4,8 centimes par ml**.* Un **assistant de recette** fait le calcul inverse : donnez-lui un volume total, un taux de nicotine visé et le taux de votre booster, il vous rend les millilitres de booster, d'arôme et de base. LifeTrack recalcule ensuite le taux de nicotine réel de la recette et vous **avertit si l'écart avec la cible dépasse 10 %**. Si vous n'avez pas envie de saisir des recettes, LifeTrack se rabat sur la **moyenne pondérée de vos achats de liquide** sur les 90 derniers jours. Moins précis, mais sans effort. **Le coût réel par jour** additionne : ``` coût/jour = ml consommés × coût au ml + (prix d'une résistance ⁄ durée de vie moyenne) ``` L'amortissement de la résistance est souvent la surprise du calcul : une résistance à 2,50 € qui tient 10 jours, c'est 25 centimes par jour, parfois plus que le liquide lui-même. L'onglet affiche en parallèle vos **dépenses réelles** (issues de vos achats saisis) : l'écart avec le coût théorique révèle vos stocks et vos achats d'impulsion. ### Étape 5 : lire ses économies Onglet **Économies**. Le principe : ``` économies cumulées = (coût tabac de référence × jours écoulés) − (coût de vape cumulé) ``` Les journées sans saisie de recharge ne sont pas comptées à zéro — ce serait tricher et gonfler artificiellement les économies. Elles sont **imputées à votre moyenne des 30 derniers jours**. Deux courbes sont proposées : les **économies théoriques** (à partir du coût au ml calculé) et les **économies réelles** (à partir de vos achats effectifs). La seconde est la vérité comptable ; la première est plus stable. À côté : cigarettes évitées, paquets évités, et **temps de vie récupéré** (compté sur la base de 11 minutes par cigarette). L'équivalence nicotine ↔ cigarettes est donnée à titre indicatif sur la base de 12 mg par cigarette — c'est un ordre de grandeur, pas une mesure. Enfin, les **jalons santé** : douze étapes datées depuis votre arrêt, de la fréquence cardiaque qui redescend après 20 minutes jusqu'au risque coronarien redevenu normal après 15 ans, avec la progression vers le prochain palier. --- ## Finances ### Étape 1 : exporter un relevé depuis sa banque Connectez-vous à l'espace client de votre banque et cherchez « Télécharger », « Exporter » ou « Historique des opérations ». **Préférez toujours l'OFX au CSV quand il est proposé** : ce format embarque un identifiant unique par opération, ce qui rend la déduplication parfaite. Presets intégrés à LifeTrack : | Banque | Format testé | À savoir | |---|---|---| | **BoursoBank / Boursorama** | CSV `;`, UTF-8 | Plusieurs années disponibles, période libre | | **Crédit Agricole** | CSV `;`, ISO-8859-15 | Préambule de longueur variable ; 30 à 90 jours selon la caisse | | **BNP Paribas** | CSV `;`, ISO-8859-1 | Première ligne = solde, pas d'en-tête de colonnes ; environ 90 jours | | **Société Générale** | CSV `;`, ISO-8859-1 | Environ 6 mois d'historique | | **La Banque Postale** | CSV `;`, ISO-8859-15 | Préambule d'environ 8 lignes ; environ 90 jours | | **Caisse d'Épargne** | CSV `;`, ISO-8859-1 | Colonnes Débit/Crédit séparées, crédit préfixé `+` | | **Fortuneo** | CSV `;`, encodage détecté | Jusqu'à environ 10 ans d'historique | | **Revolut** | CSV `,`, UTF-8 | Historique complet ; les frais sont déduits du montant | | **N26** | CSV `,`, UTF-8 | Historique complet | | **PayPal** | CSV `,` | Rapport d'activité, 7 ans par tranches de 12 mois | | **OFX** | `.ofx` / `.qfx` | Toutes banques — **à privilégier** | | **CSV générique** | tout CSV | Avec mappage de colonnes ajustable | Une banque absente de la liste ? Le **CSV générique** avec l'éditeur de mappage traite n'importe quel fichier tabulaire. > Les banques modifient la mise en page de leurs exports sans prévenir. C'est précisément > pour cela que l'aperçu existe : **vérifiez-le systématiquement**. ### Étape 2 : créer un compte de destination Avant le premier import, créez le compte correspondant dans **Finances → Comptes** : un nom, un type (courant, épargne, PayPal, espèces). Chaque transaction est rattachée à un compte — c'est ce qui permet ensuite de détecter les virements entre vos propres comptes. ### Étape 3 : l'aperçu avant import Déposez le fichier depuis **Imports** ou depuis le module **Finances**, choisissez le compte et le profil bancaire. **Rien n'est écrit en base à ce stade.** L'aperçu vous montre : - les **20 premières lignes** telles que LifeTrack les a comprises : date, libellé, montant ; - le nombre de lignes lues, de **doublons qui seront ignorés**, et de lignes en erreur ; - la **période couverte** par le fichier ; - un avertissement si ce fichier a **déjà été importé** à l'identique. Contrôlez trois choses : les dates ne sont pas inversées (13/08 ne doit pas devenir le 8 mars), les montants ont le bon signe (les dépenses en négatif), les libellés ne sont pas tronqués ni truffés de caractères bizarres. Si quelque chose cloche, ouvrez **Ajuster le mappage** : séparateur, encodage, séparateur décimal, format de date, lignes d'en-tête à ignorer, correspondance des colonnes, mode des montants (une colonne signée, ou colonnes Débit/Crédit séparées). Vos réglages sont enregistrés dans un **profil personnel** — le preset d'origine n'est jamais modifié. Ensuite seulement, **Lancer l'import**. ### Étape 4 : la déduplication lors des ré-imports C'est le point qui permet de ne pas réfléchir. **Vous pouvez ré-importer le même fichier autant de fois que vous voulez, et importer des fichiers qui se chevauchent : aucune transaction ne sera dupliquée.** Deux mécanismes : 1. **Identifiant externe** — quand la source en fournit un (FITID de l'OFX, identifiant de transaction PayPal), il fait foi. C'est le cas idéal. 2. **Empreinte de contenu** — sinon, LifeTrack calcule une empreinte à partir du compte, de la date comptable, du montant et du libellé. Un **numéro d'occurrence** distingue les opérations légitimement identiques (deux cafés à 2,50 € le même jour au même endroit sont bien deux transactions, pas un doublon). Conséquence pratique : téléchargez le relevé du mois entier chaque mois sans vous soucier des chevauchements. Seules les nouvelles opérations seront ajoutées. ### Étape 5 : les règles de catégorisation Une arborescence de catégories françaises complète est créée automatiquement au premier usage (Alimentation, Logement, Transports, Santé, Loisirs, Shopping, Vape & tabac, Banque & frais, Impôts & taxes… et côté revenus : Salaire, Aides & prestations, Remboursements, Ventes…). Dans **Finances → Transactions**, une règle se compose de **conditions** et d'**actions** : | Condition | Effet | |---|---| | **Libellé contient** | Correspondance textuelle simple — commencez toujours par là | | **Expression régulière** | Pour les cas tordus ; une expression invalide est refusée avec un message clair | | **Sens** | Débit, crédit, ou indifférent | | **Montant minimum / maximum** | Fourchette | | **Compte** | Restreindre à un compte | Chaque règle porte une **priorité** ; on peut les réordonner. Par défaut une règle qui correspond **arrête** l'évaluation des suivantes. Trois garde-fous utiles : - **Aperçu d'une règle** avant de l'enregistrer : vous voyez exactement quelles transactions existantes elle attraperait. - **Application en masse**, avec un choix de portée : uniquement les non catégorisées, toutes celles qui n'ont pas été classées à la main, ou vraiment toutes. - **Mode simulation** (`dry_run`) : LifeTrack compte ce qu'il changerait sans rien changer. > **Vos décisions manuelles sont sacrées.** Une transaction que vous avez catégorisée > vous-même n'est jamais réécrite par une règle, sauf demande explicite de forçage. Vous > pouvez lancer vos règles sans crainte de perdre votre travail de tri. Il existe aussi une **catégorisation en masse** directe, pour sélectionner plusieurs transactions et les classer d'un coup sans écrire de règle. ### Étape 6 : les budgets Dans **Finances → Budgets**, définissez un montant mensuel par catégorie, avec un mois de début et éventuellement un mois de fin. LifeTrack affiche pour le mois en cours le budget, le réalisé, le restant, le pourcentage d'avancement et une **projection de fin de mois** basée sur votre rythme de dépense actuel — l'indicateur qui permet de corriger le tir avant le 30. Un budget peut être révisé sans perdre son historique : la nouvelle valeur s'applique à partir du mois que vous indiquez. ### Étape 7 : les virements internes Quand vous déplacez 500 € de votre compte courant vers votre livret, ce n'est **pas** une dépense. Sans traitement, ces mouvements polluent tous vos graphiques. **Finances → Aperçu → Détecter les virements** cherche les paires de transactions qui s'annulent : montants opposés, sur deux comptes différents, à **moins de 3 jours d'intervalle**, avec un libellé évocateur (`VIR`, `VIREMENT`, `TRANSFERT`, `PAYPAL`). Les paires trouvées sont classées dans la catégorie système **« Virements internes »** et exclues des totaux de dépenses. La détection n'est pas infaillible : vous pouvez **lier deux transactions à la main**, ou **délier** une paire mal appariée. ### Étape 8 : les récurrents **Finances → Récurrents** détecte tout seul vos abonnements et prélèvements réguliers, sans que vous ayez rien à déclarer. Une série est reconnue à partir de **3 occurrences** au moins, avec un intervalle régulier : | Périodicité | Intervalle accepté | |---|---| | Hebdomadaire | 6 à 8 jours | | Mensuelle | 25 à 35 jours | | Trimestrielle | 85 à 97 jours | | Annuelle | 350 à 380 jours | Pour chaque série : le montant moyen, le montant attendu, la dernière date, la **prochaine échéance prédite**, et si elle est toujours active. En haut de page, le **total mensuel estimé** ramène tout à une base mensuelle (une dépense annuelle compte pour un douzième) : c'est le montant qui part de votre compte chaque mois avant même que vous ayez décidé quoi que ce soit. --- ## Dépannage ### « Mon fichier CSV est refusé » / la détection automatique se trompe Dans l'ordre : 1. **Vérifiez l'extension.** LifeTrack ne se fie pas qu'au contenu : `.csv`, `.txt` pour les relevés bancaires, `.ofx` ou `.qfx` pour l'OFX. Un fichier renommé `.xls` sera rejeté même s'il contient du CSV. 2. **Vérifiez la taille : 20 Mio maximum.** Au-delà, découpez l'export par périodes. 3. **Choisissez le profil à la main** au lieu de « Détection automatique ». La détection s'appuie sur les en-têtes des 4 096 premiers octets ; un export exotique ou un préambule inhabituel peut la mettre en défaut. 4. **Ouvrez « Ajuster le mappage »** si l'aperçu est vide ou incohérent. Les suspects habituels : le séparateur (`;` en France, `,` pour Revolut, N26 et PayPal), l'encodage (`cp1252` pour la plupart des banques françaises, `utf-8` pour les néobanques) et le format de date (`%d/%m/%Y` contre `%Y-%m-%d`). 5. **Message « Aucune ligne exploitable — vérifiez le profil de source »** : le fichier a bien été lu, mais aucune ligne n'a produit de transaction. C'est presque toujours un profil inadapté, pas un fichier corrompu. Après l'import, le **rapport d'erreurs** est téléchargeable en CSV depuis l'historique : il indique le numéro de ligne et le motif de chaque rejet. Les 100 premières erreurs sont conservées. ### « J'ai des doublons » Rappel : le ré-import du même fichier n'en crée jamais. Si vous en voyez malgré tout : - **La même opération saisie à la main *et* importée** — la déduplication ne joue qu'entre lignes importées. Supprimez celle de trop. - **Deux sources décrivant le même événement** — par exemple une séance de sport arrivée à la fois par Health Connect et par un CSV. Les séances qui se chevauchent à plus de 80 % sont signalées comme doublons potentiels, mais elles restent deux lignes distinctes : c'est volontaire, chaque source garde ses données. - **Deux comptes bancaires pour le même relevé** — la déduplication est calculée **par compte**. Importer le même fichier sur deux comptes crée bien deux jeux de transactions. Vérifiez le compte de destination. - **Le même relevé importé avec deux profils différents** — les libellés interprétés différemment produisent des empreintes différentes. Annulez l'un des deux lots. Pour les activités quotidiennes (pas, calories), il n'y a pas de doublon possible : une seule ligne existe par jour et par source, et les sources sont fusionnées **champ par champ** selon un ordre de priorité (saisie manuelle, puis Health Connect, puis les autres). LifeTrack n'additionne jamais deux sources — ce serait le meilleur moyen de compter ses pas deux fois. ### « Les dates ou les heures sont décalées » - **Une donnée apparaît la veille ou le lendemain.** Tout est stocké en UTC et réaffiché dans votre fuseau. Vérifiez le **fuseau horaire du profil** (`Réglages → Profil`, `Europe/Paris` par défaut). Une pesée à 00 h 30 heure française est enregistrée à 22 h 30 UTC la veille : si le fuseau est mal réglé, elle tombe le mauvais jour. - **Un horodatage sans fuseau** (fréquent dans les exports CSV et chez Foodvisor) est interprété en **Europe/Paris**, jamais en UTC. C'est le bon choix dans 99 % des cas, mais cela décale les données d'un export produit dans un autre pays. - **Un jour de plus ou de moins autour du changement d'heure** : les agrégations journalières utilisent le fuseau, pas un décalage fixe. Un décalage résiduel sur les journées de transition n'est pas anormal. - **Les dates du relevé bancaire sont fausses** (le 04/03 devient le 3 avril) : mauvais format de date dans le profil. Corrigez `date_format` dans le mappage et **annulez puis ré-importez** le lot. ### « Module vape non configuré » Le module refuse de calculer tant que la **référence tabac** n'est pas saisie. Allez dans **Réglages → Vape** et renseignez au minimum la date d'arrêt, les cigarettes par jour avant l'arrêt et le prix du paquet. Autres cas voisins : - **Aucun coût affiché** : il faut soit au moins une recette avec ses composants et leurs prix, soit au moins un achat de liquide enregistré. Sans l'un ou l'autre, LifeTrack ne peut pas connaître votre coût au ml — et préfère n'afficher aucun chiffre plutôt qu'un chiffre faux. - **Durée de vie des résistances à 14 jours** : c'est la valeur par défaut tant qu'il n'y a pas eu **deux changements** enregistrés. Elle deviendra réelle dès le deuxième clic. - **Économies qui semblent trop belles** : vérifiez la proportion de jours suivis. Si vous ne saisissez vos recharges qu'une fois sur trois, l'imputation par la moyenne fait le reste et la précision s'en ressent. ### Annuler un import (rollback) Tout lot d'import est réversible. 1. Ouvrez **Imports** (ou **Finances** pour un relevé bancaire). 2. Dans **Historique des imports**, repérez la ligne concernée. 3. Cliquez sur **Annuler cet import**. 4. Confirmez : le nombre exact de lignes qui seront supprimées vous est indiqué. Les données créées par ce lot disparaissent des tableaux de bord. **Le fichier peut être ré-importé ensuite** — c'est la manœuvre normale quand on s'aperçoit après coup qu'on a choisi le mauvais profil ou le mauvais compte : on annule, on corrige le mappage, on recommence. **Cas particulier des transactions modifiées à la main.** Si vous avez catégorisé vous-même ou annoté des transactions du lot, LifeTrack **refuse l'annulation** et vous avertit. Vous pouvez alors cocher **« Supprimer quand même les lignes modifiées manuellement »** pour forcer. C'est irréversible : votre travail de catégorisation sur ces lignes sera perdu. ### « Open Food Facts est injoignable » Message attendu si votre serveur n'a pas d'accès Internet ou si le service est indisponible. Ce n'est pas bloquant : - les aliments **déjà consultés** restent disponibles dans le cache local ; - la **saisie manuelle** fonctionne toujours ; - réessayez plus tard, la recherche repartira sans rien perdre. Si la recherche est simplement vide, vérifiez que vous avez tapé au moins **2 caractères**. ### « La passerelle Health Connect n'envoie rien » Dans l'ordre : 1. **Regardez la colonne « Dernière utilisation »** dans **Réglages → Appareils & API**. Toujours « Jamais » ? Aucune requête n'est jamais arrivée : le problème est côté réseau ou côté application. 2. **Testez l'endpoint avec `curl`** (exemple plus haut). Si `curl` fonctionne, LifeTrack n'est pas en cause. 3. **Vérifiez l'en-tête `X-API-Key`.** C'est la cause numéro un — voir plus haut : la passerelle `health-connect-webhook` **ne sait pas poser d'en-tête**, elle ne peut donc pas fonctionner en direct. 4. **Vérifiez la portée de la clé.** Une erreur 403 « Cette clé d'appareil ne dispose pas du droit requis » signifie qu'il manque `ingest:health`. 5. **Erreur 404 « Domaine d'ingestion inconnu »** : seul le domaine `health` est traité aujourd'hui. `POST /api/ingest/vape` et `POST /api/ingest/finance` n'existent pas encore, même si les portées correspondantes sont proposées à la création d'une clé. 6. **Le téléphone atteint-il le serveur ?** Depuis le navigateur du téléphone, ouvrez `http:///api/healthz`. Vous devez voir `{"status":"ok"}`. Sinon, c'est un problème de réseau local, de pare-feu ou de VPN. 7. **Économiseur de batterie** : excluez l'application des optimisations Android. ### L'application ne démarre pas du tout ```bash docker compose ps # quels conteneurs tournent docker compose logs api # journaux du backend docker compose logs web # journaux de nginx ``` - **`api` redémarre en boucle** : presque toujours la base. Vérifiez que `POSTGRES_PASSWORD` dans `.env` correspond bien à celui avec lequel le volume a été créé. Si vous avez changé le mot de passe **après** le premier démarrage, l'ancien volume conserve l'ancien : soit vous remettez l'ancien mot de passe, soit vous repartez de zéro avec `docker compose down -v` (**qui efface toutes vos données**). - **Page blanche sur `http://localhost`** : `web` tourne mais `api` non. Regardez les journaux de `api`. - **Port déjà utilisé** : changez `WEB_PORT` dans `.env` (par exemple `8080`) puis relancez. - **Déconnexion permanente / boucle vers l'écran de connexion** : `LIFETRACK_JWT_SECRET` a changé entre deux démarrages, ce qui invalide tous les jetons existants. Reconnectez-vous une fois, et ne modifiez plus ce secret. > Rappel : la pile Docker Compose **n'a jamais été démarrée pendant le développement** (le > démon Docker était indisponible). Si le tout premier `docker compose up --build` bute sur > un détail d'infrastructure, ce n'est pas anormal — commencez toujours par lire les journaux > du conteneur fautif.