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