diff --git a/.gitignore b/.gitignore index b0af335..0d9b13a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ __pycache__/ instance/ .env *.db +.ruff_cache/ +.pytest_cache/ diff --git a/app/__init__.py b/app/__init__.py index 5856e50..04f75a5 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -14,9 +14,9 @@ Architecture et composants clés : """ import os +import tomllib import sqlalchemy as sa -import tomllib from flask import Flask from flask_sqlalchemy import SQLAlchemy diff --git a/app/business/time_calc.py b/app/business/time_calc.py index c1f2fc7..30b13a6 100644 --- a/app/business/time_calc.py +++ b/app/business/time_calc.py @@ -1,3 +1,6 @@ +import statistics as _stats + + def minutes_to_str(minutes: int) -> str: """ Convertit une durée en minutes en une chaîne formatée lisible (ex: "7h45" ou "-1h15"). @@ -58,9 +61,6 @@ def week_balance_minutes(actual_minutes: int, reference_minutes: int) -> int: return actual_minutes - reference_minutes -import statistics as _stats - - def monthly_stats(entries: list) -> dict: """ Calcule la médiane journalière et la médiane hebdomadaire (semaines ISO) pour un groupe d'entrées. diff --git a/app/config_loader.py b/app/config_loader.py index 50368e7..28176dd 100644 --- a/app/config_loader.py +++ b/app/config_loader.py @@ -8,15 +8,15 @@ Contrat TOML : 1. Véhicules (`[vehicles]`) : - Chaque véhicule possède un identifiant unique (clé). - Attributs : `name` (nom d'affichage), `type` ("moteur" ou "velo"), `fuel` ("electric", "essence", etc.), - et optionnellement `cv` (puissance fiscale pour le barème kilométrique). + `co2_per_km` (émissions de CO2 en grammes par km), et optionnellement `cv` (puissance fiscale pour le barème kilométrique). 2. Trajets (`[journeys]`) : - - Profils de trajets prédéfinis (ex: "domicile-travail"). + - Profils de trajets prédéfinis (ex: "moteur_seul"). - Attributs : `name` (nom d'affichage), `distances` (dictionnaire associant un type de véhicule à une distance en km). 3. Barème kilométrique (`[bareme_kilometrique.YYYY]`) : - Organisé par année (ex: "2026") puis par puissance fiscale (`cv_3`, `cv_4`, `cv_5`, `cv_6`, `cv_7plus`). - Chaque catégorie contient une liste de `tranches` définissant les formules de calcul des frais réels. - - Une tranche possède : `km_max` (limite supérieure de la tranche, `km_max = 0` signifie "pas de limite supérieure"), - `coeff` (coefficient multiplicateur par km) et `fixe` (montant forfaitaire à ajouter). + - Une tranche possède : `km_max` (limite supérieure de la tranche, `km_max = 0` signifie "pas de limite supérieure"), + `taux` (coefficient multiplicateur par km) et `forfait` (montant forfaitaire à ajouter). 4. Types de jours sans trajet : - Certains types de journées (Télétravail, Maladie, Congé, RTT, Férié) n'impliquent aucun déplacement physique. """ @@ -29,7 +29,7 @@ def get_vehicles(): Retourne: dict: Un dictionnaire des véhicules où la clé est l'identifiant du véhicule - et la valeur est un dictionnaire contenant ses propriétés (name, type, fuel, cv). + et la valeur est un dictionnaire contenant ses propriétés (name, type, fuel, co2_per_km, cv). Retourne un dictionnaire vide si aucune configuration n'est chargée. """ return current_app.config.get("TOML", {}).get("vehicles", {}) @@ -95,7 +95,7 @@ def get_bareme(year: int, cv: int) -> list[dict]: Retourne: list[dict]: Une liste de dictionnaires représentant les tranches applicables. - Chaque tranche contient 'km_max' (0 si pas de limite), 'coeff' et 'fixe'. + Chaque tranche contient 'km_max' (0 si pas de limite), 'taux' et 'forfait'. """ bareme = current_app.config.get("TOML", {}).get("bareme_kilometrique", {}) year_data = bareme.get(str(year), {}) diff --git a/pyproject.toml b/pyproject.toml index 2dc086e..836bac7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,15 @@ [tool.ruff] -target-version = "py310" +target-version = "py311" line-length = 100 include = ["*.py"] [tool.ruff.lint] select = ["E4", "E7", "E9", "F", "I"] -# Ces imports différés sont intentionnels : ils évitent des dépendances -# circulaires ou préparent sys.path pour les scripts lancés directement. +# Cet import différé est intentionnel : il prépare sys.path pour le script +# lancé directement (imports des modules de l'app après insertion du parent). [tool.ruff.lint.per-file-ignores] -"app/business/time_calc.py" = ["E402"] "scripts/import_csv.py" = ["E402"] -"tests/test_time_calc.py" = ["E402"] [tool.ruff.format] quote-style = "double" diff --git a/scripts/import_csv.py b/scripts/import_csv.py index 1372e85..ccb4d64 100755 --- a/scripts/import_csv.py +++ b/scripts/import_csv.py @@ -33,7 +33,7 @@ from app.models import TimeSlot, WorkEntry DAY_TYPES = {"WORK", "TT", "GARDE", "ASTREINTE", "FORMATION", "RTT", "CONGE", "MALADE", "FERIE"} -def main(csv_path: str, config_path: str = None): +def main(csv_path: str, config_path: str | None = None): """Importe les données depuis un fichier CSV vers la base de données.""" # Créer l'application Flask avec la config diff --git a/tests/test_time_calc.py b/tests/test_time_calc.py index f1ac627..47861e9 100644 --- a/tests/test_time_calc.py +++ b/tests/test_time_calc.py @@ -1,8 +1,14 @@ +from datetime import date +from datetime import time as dtime + from app.business.time_calc import ( + count_day_types, minutes_to_str, + monthly_stats, week_balance_minutes, work_minutes_reference, ) +from app.models import TimeSlot, WorkEntry def test_minutes_to_str_basic(): @@ -42,13 +48,6 @@ def test_week_balance_negative(): assert week_balance_minutes(2200, 2325) == -125 -from datetime import date -from datetime import time as dtime - -from app.business.time_calc import count_day_types, monthly_stats -from app.models import TimeSlot, WorkEntry - - def test_count_day_types_basic(): entries = [ WorkEntry(date=date(2025, 1, 2), day_type="WORK"),