docs: add initial design document for work time tracking dashboard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 15:23:01 +01:00
commit 49bd75065b

View File

@@ -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.