From 49bd75065b721bd313da5ecc03b45b83882a12f5 Mon Sep 17 00:00:00 2001 From: Antoine Van Elstraete Date: Wed, 11 Mar 2026 15:23:01 +0100 Subject: [PATCH] docs: add initial design document for work time tracking dashboard Co-Authored-By: Claude Sonnet 4.6 --- ...26-03-11-tableau-de-bord-travail-design.md | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 docs/plans/2026-03-11-tableau-de-bord-travail-design.md diff --git a/docs/plans/2026-03-11-tableau-de-bord-travail-design.md b/docs/plans/2026-03-11-tableau-de-bord-travail-design.md new file mode 100644 index 0000000..fc8fafb --- /dev/null +++ b/docs/plans/2026-03-11-tableau-de-bord-travail-design.md @@ -0,0 +1,203 @@ +# Design : Tableau de bord temps de travail + +**Date :** 2026-03-11 +**Statut :** Approuvé + +--- + +## Objectif + +Application web personnelle auto-hébergée pour tracer au quotidien le temps de travail : heures de présence, déplacements domicile-travail (coût, CO2, frais réels fiscaux), solde congés/RTT. + +--- + +## Stack technique + +- **Backend :** Python 3.12+, Flask, SQLAlchemy, SQLite +- **Frontend :** Jinja2 + HTMX + Tailwind CSS (CDN Play, sans build chain) +- **Configuration :** TOML (`config.toml`) chargé au démarrage +- **Déploiement :** Gunicorn sur port local, derrière HAProxy (TLS + auth gérés en amont) + +--- + +## Structure du projet + +``` +tableau-de-bord/ +├── app/ +│ ├── __init__.py # factory Flask +│ ├── models.py # SQLAlchemy models +│ ├── routes/ +│ │ ├── dashboard.py # page principale / synthèse +│ │ ├── entries.py # saisie / édition des jours +│ │ └── reports.py # rapports (frais réels, CO2...) +│ ├── templates/ +│ │ ├── base.html +│ │ ├── dashboard.html +│ │ ├── entry.html +│ │ └── reports.html +│ └── static/ +├── config.toml +├── instance/ +│ └── worklog.db +└── run.py +``` + +--- + +## Modèle de données + +### Table `work_entries` + +| Colonne | Type | Description | +|---|---|---| +| id | INTEGER PK | | +| date | DATE UNIQUE | Date du jour | +| journey_profile_id | TEXT NULL | Clé du profil dans config.toml (null si TT/MALADE/CONGE/RTT/FERIE) | +| day_type | TEXT | Voir types ci-dessous | +| comment | TEXT NULL | Commentaire libre | +| created_at | DATETIME | | +| updated_at | DATETIME | | + +**Types de journées (`day_type`) :** +- `WORK` — Jour de travail normal sur site +- `TT` — Télétravail (7h45, pas de déplacement) +- `GARDE` — Garde physique sur site (9h-19h, weekend/férié) +- `ASTREINTE` — Disponibilité sans présence obligatoire (déplacement si besoin réel) +- `FORMATION` — Formation +- `RTT` — Jour de RTT +- `CONGE` — Congé payé +- `MALADE` — Arrêt maladie +- `FERIE` — Jour férié + +### Table `time_slots` + +| Colonne | Type | Description | +|---|---|---| +| id | INTEGER PK | | +| entry_id | INTEGER FK | Référence work_entries | +| start_time | TIME | Heure de début | +| end_time | TIME | Heure de fin | + +Une journée peut avoir N plages horaires non-consécutives (ex: 9h-18h + 22h-00h pour coupures ou réunion de nuit). Le temps total = somme des plages. + +### Table `leave_balance` + +| Colonne | Type | Description | +|---|---|---| +| id | INTEGER PK | | +| year | INTEGER UNIQUE | Année | +| conges_total | INTEGER | Total congés (défaut 28) | +| rtt_total | INTEGER | Total RTT (défaut 18) | + +Les jours utilisés sont calculés dynamiquement depuis `work_entries`. + +--- + +## Configuration TOML + +```toml +[vehicles.voiture] +name = "Peugeot 308" +fuel = "diesel" +co2_per_km = 142 # g/km + +[vehicles.velo] +name = "Vélo" +fuel = "none" +co2_per_km = 0 + +# Profils de trajet : distances par véhicule (km aller-retour) +[journeys.voiture_seule] +name = "Voiture seule" +distances = { voiture = 25 } + +[journeys.voiture_velo] +name = "Voiture + Vélo" +distances = { voiture = 14, velo = 8 } + +[journeys.velo_seul] +name = "Vélo seul" +distances = { velo = 24 } + +# Barème kilométrique officiel (mise à jour annuelle) +# Structure : puissance fiscale -> liste de tranches [km_max, taux] +# km_max = null pour la dernière tranche (pas de limite) +[bareme_kilometrique.2025.cv5] +tranches = [ + { km_max = 3000, taux = 0.548 }, + { km_max = 6000, taux = 0.316 }, + { km_max = null, taux = 0.364 }, +] + +[bareme_kilometrique.2025.cv6_7] +tranches = [ + { km_max = 3000, taux = 0.655 }, + { km_max = 6000, taux = 0.374 }, + { km_max = null, taux = 0.435 }, +] +# etc. pour les autres puissances fiscales + +# Puissance fiscale par véhicule +[vehicles.voiture] +cv = 5 +``` + +--- + +## Interface utilisateur + +### Mobile-first + +Toutes les vues sont conçues pour mobile en premier (Tailwind responsive). + +### Page Dashboard (principale) + +- **Carte "Aujourd'hui"** : boutons rapides "Arrivée" / "Départ" (horodatage automatique), sélecteur de profil de trajet +- **Synthèse semaine courante** (lun-dim) : total heures, écart vs objectif (5 × 7h45 = 38h45) +- **Synthèse mensuelle** : jours travaillés, km par véhicule, CO2 +- **Solde congés/RTT** : jauge visuelle (ex: "12/18 RTT utilisés") + +### Page Saisie / Édition d'un jour + +- Sélecteur de date +- Type de journée (boutons radio visuels) +- Plages horaires : liste de paires heure début/fin, bouton "+ Ajouter une plage" (via HTMX) +- Profil de trajet (masqué si TT, MALADE, CONGE, RTT, FERIE) +- Commentaire libre + +### Page Rapports + +- **Frais réels** : total annuel, détail par véhicule, tableau récapitulatif +- **CO2** : total annuel par véhicule +- **Historique mensuel** : tableau des jours avec filtres + +--- + +## Calculs métier + +### Temps de travail +- Référence : 7h45/jour, 5j/semaine (38h45/semaine) +- GARDE : 10h (9h-19h) +- ASTREINTE : selon les plages time_slots renseignées +- Temps total d'une journée = somme des time_slots + +### Frais kilométriques (frais réels) +- Utilise le barème kilométrique officiel configuré dans config.toml +- Calcul annuel : total km voiture × taux selon tranche kilométrique et puissance fiscale + +### CO2 +- CO2 (g) = km × co2_per_km (configuré par véhicule) + +### Solde congés/RTT +- Déduit dynamiquement depuis work_entries (count des day_type = CONGE/RTT pour l'année) + +--- + +## Déploiement + +``` +HAProxy (TLS + auth basic) → Gunicorn (127.0.0.1:5000) → Flask app +``` + +Pas de gestion d'authentification dans l'application elle-même.