Co-authored-by: OpenAI/GPT-5.6-Terra <vibecoder@antoineve.me> Co-authored-by: Google/Gemini-3.5-Flash <vibecoder@antoineve.me> Co-authored-by: DeepSeek/DeepSeek-v4-Flash <vibecoder@antoineve.me>
276 lines
14 KiB
Markdown
276 lines
14 KiB
Markdown
# Guide d'intégration (Onboarding) pour les développeurs
|
|
|
|
Bienvenue sur le projet **Tableau de bord pro** ! Ce guide est conçu pour t'aider à prendre en main rapidement l'application, comprendre son architecture, ses règles métier et savoir comment y apporter des modifications courantes.
|
|
|
|
---
|
|
|
|
## 1. Objectif fonctionnel
|
|
|
|
Le **Tableau de bord pro** est une application web personnelle permettant de suivre :
|
|
- **Le temps de travail quotidien** : saisie des heures travaillées, des types de journées (travail, télétravail, garde, astreinte, formation, RTT, congé, maladie, férié) et des commentaires associés.
|
|
- **Les déplacements professionnels** : calcul automatique des distances parcourues par véhicule, estimation des émissions de CO₂ et calcul des frais réels déductibles selon le barème kilométrique fiscal officiel.
|
|
- **Le solde des congés et RTT** : suivi annuel des jours posés et du solde restant par rapport aux quotas alloués.
|
|
- **Les rapports d'activité** : bilans annuels et mensuels compilant les kilomètres, le CO₂, les frais réels et la répartition des types de journées.
|
|
|
|
---
|
|
|
|
## 2. Prérequis et démarrage local
|
|
|
|
### Prérequis
|
|
- **Python 3.11+** installé sur ta machine.
|
|
|
|
### Démarrage local
|
|
Pour lancer l'application en mode développement, exécute les commandes suivantes dans ton terminal :
|
|
|
|
```bash
|
|
# 1. Créer l'environnement virtuel Python
|
|
python -m venv .venv
|
|
|
|
# 2. Activer l'environnement virtuel et installer les dépendances
|
|
.venv/bin/pip install -r requirements.txt
|
|
|
|
# 3. Lancer le serveur de développement Flask
|
|
.venv/bin/python run.py
|
|
```
|
|
|
|
L'application est alors accessible localement à l'adresse suivante : [http://localhost:5000](http://localhost:5000).
|
|
|
|
---
|
|
|
|
## 3. Architecture de l'application
|
|
|
|
L'application est construite avec le framework **Flask** en utilisant le *Factory Pattern* (via la fonction `create_app` dans `app/__init__.py`).
|
|
|
|
### Structure des dossiers et fichiers clés
|
|
- `run.py` : Point d'entrée pour lancer le serveur de développement.
|
|
- `config.toml` : Fichier de configuration statique (véhicules, trajets, barèmes fiscaux).
|
|
- `app/` : Code source de l'application.
|
|
- `__init__.py` : Initialisation de Flask, configuration de la base de données, enregistrement des blueprints et des filtres Jinja2.
|
|
- `config_loader.py` : Interface de lecture du fichier `config.toml`.
|
|
- `models.py` : Définition des modèles de données SQLAlchemy (SQLite).
|
|
- `business/` : Logique métier pure, **sans dépendance à Flask** (facile à tester) :
|
|
- `time_calc.py` : Calculs de durées, de soldes d'heures et statistiques de temps.
|
|
- `travel_calc.py` : Calculs de distances, d'émissions de CO₂ et de frais réels.
|
|
- `leave_calc.py` : Calculs de congés et RTT consommés.
|
|
- `routes/` : Contrôleurs Flask gérant les requêtes HTTP et le rendu des templates :
|
|
- `dashboard.py` : Page d'accueil et vue d'ensemble.
|
|
- `entries.py` : Gestion (CRUD) des entrées de temps.
|
|
- `reports.py` : Génération des rapports annuels et mensuels.
|
|
- `templates/` : Fichiers HTML utilisant Jinja2.
|
|
- `tests/` : Tests unitaires et d'intégration (pytest).
|
|
|
|
### Technologies Frontend
|
|
- **Tailwind CSS (via CDN)** : Utilisé pour le style. Les variables de design et les classes personnalisées (comme `.card`, `.btn-primary`, etc.) sont définies directement dans la balise `<style>` de `app/templates/base.html`.
|
|
- **HTMX** : Utilisé pour rendre l'interface dynamique sans rechargement complet de page.
|
|
- **JavaScript** : Uniquement du JS inline dans `app/templates/entry_form.html` pour la gestion dynamique du formulaire de saisie.
|
|
|
|
### Authentification
|
|
L'application n'intègre **aucun système d'authentification interne**. La sécurité et l'authentification sont entièrement déléguées à un serveur **HAProxy** situé en amont (upstream) en production.
|
|
|
|
---
|
|
|
|
## 4. Flux d'une saisie de journée
|
|
|
|
Voici ce qui se passe lorsqu'un utilisateur saisit ou modifie une journée de travail :
|
|
|
|
1. **Affichage du formulaire (GET `/entries/new` ou `/entries/<id>/edit`)** :
|
|
- La route `entry_form` dans `app/routes/entries.py` récupère les véhicules à moteur et les profils de trajets depuis `config.toml` via `app/config_loader.py`.
|
|
- Elle transmet ces données au template `entry_form.html`.
|
|
|
|
2. **Soumission du formulaire (POST)** :
|
|
- L'utilisateur envoie la date, le type de journée, le trajet, le véhicule à moteur utilisé, le commentaire et les plages horaires.
|
|
- **Application des règles de cohérence** :
|
|
- Si le type de journée est un jour sans trajet (ex: Télétravail, Congé), le trajet est forcé à `None`.
|
|
- Si le trajet sélectionné n'implique pas de véhicule à moteur, le véhicule à moteur est forcé à `None`.
|
|
- **Enregistrement de l'entrée (`WorkEntry`)** :
|
|
- En création, l'application vérifie qu'aucune entrée n'existe déjà à cette date (unicité de la date).
|
|
- L'entrée est créée ou mise à jour dans la table `work_entries`.
|
|
- **Gestion des plages horaires (`TimeSlot`)** :
|
|
- Pour simplifier la mise à jour, toutes les plages horaires existantes de cette journée sont **supprimées** de la base de données.
|
|
- Les nouvelles plages horaires soumises sont lues, validées et recréées sous forme d'objets `TimeSlot` liés à la `WorkEntry`.
|
|
- **Validation** : La transaction est validée via `db.session.commit()`, et l'utilisateur est redirigé vers le tableau de bord.
|
|
|
|
---
|
|
|
|
## 5. Rôle de `config.toml` vs SQLite
|
|
|
|
L'application sépare strictement la configuration métier statique des données utilisateur dynamiques.
|
|
|
|
### `config.toml` (Configuration statique)
|
|
Ce fichier contient les paramètres qui ne changent pas fréquemment et qui définissent les règles de calcul :
|
|
- **Véhicules (`[vehicles.*]`)** : Nom, type (moteur ou velo), carburant (electric, diesel, essence, none), émissions de CO₂ par km, et puissance fiscale (CV).
|
|
- **Trajets (`[journeys.*]`)** : Profils de trajets prédéfinis (ex: "moteur_seul", "moteur_velo") avec les distances associées par type de moyen de transport.
|
|
- **Barème kilométrique (`[bareme_kilometrique.YYYY.*]`)** : Les tranches fiscales officielles de remboursement par année et par puissance fiscale (CV).
|
|
|
|
*Note : Ces données sont chargées en mémoire au démarrage de l'application dans `app.config["TOML"]`.*
|
|
|
|
### SQLite / `instance/worklog.db` (Données dynamiques)
|
|
La base de données stocke l'activité saisie par l'utilisateur :
|
|
- **`work_entries`** : Une ligne par jour saisi (date, type de jour, ID du trajet, ID du véhicule, commentaire, timestamps).
|
|
- **`time_slots`** : Les plages horaires travaillées associées à une journée (heure de début, heure de fin, ID de l'entrée).
|
|
- **`leave_balance`** : Les quotas annuels de congés et de RTT (année, total congés, total RTT).
|
|
|
|
---
|
|
|
|
## 6. Règles métier essentielles
|
|
|
|
Pour éviter les erreurs de calcul, garde bien en tête ces règles fondamentales :
|
|
|
|
- **Types de journées** : Les types autorisés sont `WORK`, `TT`, `GARDE`, `ASTREINTE`, `FORMATION`, `RTT`, `CONGE`, `MALADE`, `FERIE`.
|
|
- **Absence de trajet** : Les types `TT`, `MALADE`, `CONGE`, `RTT` et `FERIE` n'impliquent aucun trajet physique (définis dans `day_types_without_journey()`).
|
|
- **Durée de référence du travail** :
|
|
- `WORK`, `TT`, `FORMATION` : 7h45 (soit 465 minutes).
|
|
- `GARDE` : 10h00 (soit 600 minutes).
|
|
- `ASTREINTE`, `RTT`, `CONGE`, `MALADE`, `FERIE` : 0 minute.
|
|
- **Calcul du temps de travail** : La méthode `total_minutes()` de `WorkEntry` somme les durées des `TimeSlot`. Elle gère le **passage de minuit** : si l'heure de fin est inférieure ou égale à l'heure de début (ex: 22:00 à 02:00), elle ajoute automatiquement 24 heures à la plage.
|
|
- **Frais réels et véhicules électriques** :
|
|
- Le calcul des frais réels applique les tranches du barème kilométrique de `config.toml`. Une tranche avec `km_max = 0` représente la tranche supérieure sans limite.
|
|
- Les véhicules électriques (`fuel = "electric"`) bénéficient d'une **majoration automatique de 20 %** sur le montant calculé des frais réels (géré dans `app/business/travel_calc.py`).
|
|
|
|
---
|
|
|
|
## 7. Tests et Qualité du code
|
|
|
|
### Exécuter les tests
|
|
Les tests sont écrits avec **pytest**. Les tests de logique métier (`test_time_calc.py`, `test_travel_calc.py`) n'ont aucune dépendance à Flask et s'exécutent très rapidement. Les tests de routes utilisent des fixtures définies dans `tests/conftest.py` (base de données SQLite en mémoire et configuration TOML temporaire).
|
|
|
|
```bash
|
|
# Exécuter tous les tests
|
|
.venv/bin/python -m pytest
|
|
|
|
# Exécuter un fichier de test spécifique
|
|
.venv/bin/python -m pytest tests/test_time_calc.py -v
|
|
|
|
# Exécuter un test unitaire précis
|
|
.venv/bin/python -m pytest tests/test_routes.py::test_create_entry -v
|
|
```
|
|
|
|
### Qualité et Formatage du code
|
|
Le projet utilise **Ruff** comme outil unique pour le linting, le tri des imports et le formatage du code. La configuration est définie dans `pyproject.toml`.
|
|
|
|
```bash
|
|
# Vérifier le code (linter)
|
|
.venv/bin/ruff check .
|
|
|
|
# Vérifier le formatage
|
|
.venv/bin/ruff format --check .
|
|
|
|
# Appliquer automatiquement le formatage et corriger les imports
|
|
.venv/bin/ruff format .
|
|
.venv/bin/ruff check --fix .
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Guide de modifications courantes
|
|
|
|
### A. Ajouter ou modifier un véhicule
|
|
Pour ajouter un nouveau véhicule (par exemple, une nouvelle voiture de 4 CV), ouvre `config.toml` et ajoute une section sous `[vehicles]` :
|
|
```toml
|
|
[vehicles.ma_nouvelle_voiture]
|
|
name = "Ma Nouvelle Voiture"
|
|
fuel = "essence"
|
|
co2_per_km = 120
|
|
cv = 4
|
|
type = "moteur"
|
|
```
|
|
|
|
### B. Ajouter ou modifier un trajet prédéfini
|
|
Pour ajouter un trajet combinant voiture et vélo, ouvre `config.toml` et ajoute une section sous `[journeys]` :
|
|
```toml
|
|
[journeys.mon_nouveau_trajet]
|
|
name = "Mon Nouveau Trajet"
|
|
distances = { moteur = 10, velo = 5 }
|
|
```
|
|
|
|
### C. Mettre à jour le barème kilométrique annuel
|
|
Chaque année, l'administration fiscale publie un nouveau barème. Pour l'ajouter (par exemple pour l'année 2027), ajoute les tranches correspondantes dans `config.toml` :
|
|
```toml
|
|
[[bareme_kilometrique.2027.cv_4.tranches]]
|
|
km_max = 5000
|
|
taux = 0.606
|
|
forfait = 0
|
|
|
|
[[bareme_kilometrique.2027.cv_4.tranches]]
|
|
km_max = 20000
|
|
taux = 0.340
|
|
forfait = 1330
|
|
|
|
[[bareme_kilometrique.2027.cv_4.tranches]]
|
|
km_max = 0
|
|
taux = 0.407
|
|
forfait = 0
|
|
```
|
|
|
|
### D. Ajouter un nouveau type de journée
|
|
Si tu dois ajouter un nouveau type de journée (par exemple `REPOS`) :
|
|
1. Ouvre `app/routes/entries.py` et ajoute le type à la liste `DAY_TYPES` :
|
|
```python
|
|
DAY_TYPES = [
|
|
...
|
|
("REPOS", "Repos"),
|
|
]
|
|
```
|
|
2. Ouvre `app/__init__.py` et ajoute sa traduction française dans `_DAY_TYPE_LABELS` :
|
|
```python
|
|
_DAY_TYPE_LABELS = {
|
|
...
|
|
"REPOS": "Repos",
|
|
}
|
|
```
|
|
3. Ouvre `app/business/time_calc.py` et définis sa durée de référence dans `_REFERENCE_MINUTES` (ex: 0 minute pour un repos) :
|
|
```python
|
|
_REFERENCE_MINUTES = {
|
|
...
|
|
"REPOS": 0,
|
|
}
|
|
```
|
|
4. Si ce type de journée n'implique aucun trajet, ouvre `app/config_loader.py` et ajoute-le dans `day_types_without_journey()` :
|
|
```python
|
|
def day_types_without_journey():
|
|
return {"TT", "MALADE", "CONGE", "RTT", "FERIE", "REPOS"}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Déploiement, limites et migrations
|
|
|
|
### Déploiement en production
|
|
L'application est déployée dans `/var/www/tableau-de-bord-pro/` et est gérée par un service **systemd** qui lance **Gunicorn**.
|
|
|
|
Pour mettre à jour la production :
|
|
```bash
|
|
# 1. Copier les fichiers (en excluant l'environnement virtuel et la base de données locale)
|
|
sudo rsync -a --exclude='.venv' --exclude='instance' . /var/www/tableau-de-bord-pro/
|
|
|
|
# 2. Se positionner dans le dossier de production
|
|
cd /var/www/tableau-de-bord-pro
|
|
|
|
# 3. Mettre à jour les dépendances si nécessaire
|
|
sudo .venv/bin/pip install -r requirements.txt
|
|
|
|
# 4. S'assurer que les permissions sont correctes
|
|
sudo chown -R www-data:www-data /var/www/tableau-de-bord-pro
|
|
|
|
# 5. Redémarrer le service systemd
|
|
sudo systemctl restart tableau-de-bord-pro
|
|
```
|
|
|
|
### Limites et Migrations de base de données
|
|
- **Pas d'Alembic** : Le projet n'utilise pas d'outil de migration automatique comme Alembic. La base de données est initialisée avec `db.create_all()`.
|
|
- **Changement de schéma** : Si tu modifies un modèle dans `app/models.py` (par exemple en ajoutant un champ) :
|
|
- En **développement** : Tu peux simplement supprimer le fichier `instance/worklog.db` pour qu'il soit recréé au prochain démarrage (attention, cela supprime tes données de test).
|
|
- En **production** : Tu dois écrire une migration manuelle dans la fonction `_migrate_db` située dans `app/__init__.py`. Cette fonction s'exécute au démarrage de l'application, vérifie l'existence des colonnes via SQLite, et applique les instructions `ALTER TABLE` nécessaires de manière sécurisée.
|
|
|
|
### Dépréciations à surveiller
|
|
- **`datetime.utcnow()`** : Cette méthode est dépréciée depuis Python 3.12. Il est formellement recommandé d'utiliser `datetime.now(UTC)` (avec `from datetime import UTC`) à la place. Lors d'une prochaine évolution majeure des modèles, il faudra remplacer les occurrences existantes.
|
|
- **`db.get_engine()`** : Déprécié dans Flask-SQLAlchemy 3.x. Utilise toujours `db.engine` à la place.
|
|
|
|
---
|
|
|
|
## 10. Liens utiles
|
|
|
|
Pour aller plus loin, n'hésite pas à consulter les documents suivants à la racine du projet :
|
|
- [README.md](../README.md) : Présentation générale, instructions d'installation détaillées et script d'import CSV en masse.
|
|
- [AGENTS.md](../AGENTS.md) : Guide de développement et consignes pour les agents d'intelligence artificielle travaillant sur ce dépôt.
|