Files
tableau-de-bord/docs/plans/2026-03-11-tableau-de-bord-travail-design.md

204 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.