5.6 KiB
5.6 KiB
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 siteTT— 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— FormationRTT— Jour de RTTCONGE— Congé payéMALADE— Arrêt maladieFERIE— 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
[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.