feat: compute_km_for_entry resolves generic moteur key to specific vehicle
This commit is contained in:
@@ -1,11 +1,29 @@
|
|||||||
def compute_km_for_entry(journey_profile_id: str | None, journeys: dict) -> dict[str, int]:
|
def compute_km_for_entry(
|
||||||
|
journey_profile_id: str | None,
|
||||||
|
journeys: dict,
|
||||||
|
motor_vehicle_id: str | None = None,
|
||||||
|
) -> dict[str, int]:
|
||||||
|
"""
|
||||||
|
Retourne un dict {vehicle_id: km} pour un profil de trajet donné.
|
||||||
|
La clé générique 'moteur' est remplacée par motor_vehicle_id si fourni.
|
||||||
|
Retourne {} si pas de profil (TT, CONGE, etc.).
|
||||||
|
"""
|
||||||
if not journey_profile_id:
|
if not journey_profile_id:
|
||||||
return {}
|
return {}
|
||||||
profile = journeys.get(journey_profile_id, {})
|
profile = journeys.get(journey_profile_id, {})
|
||||||
return dict(profile.get("distances", {}))
|
distances = dict(profile.get("distances", {}))
|
||||||
|
|
||||||
|
if "moteur" in distances:
|
||||||
|
motor_km = distances.pop("moteur")
|
||||||
|
if motor_vehicle_id:
|
||||||
|
distances[motor_vehicle_id] = motor_km
|
||||||
|
# Si pas de motor_vehicle_id, la distance moteur est ignorée
|
||||||
|
|
||||||
|
return distances
|
||||||
|
|
||||||
|
|
||||||
def compute_co2_grams(km_by_vehicle: dict[str, int], vehicles: dict) -> float:
|
def compute_co2_grams(km_by_vehicle: dict[str, int], vehicles: dict) -> float:
|
||||||
|
"""Calcule le CO2 total en grammes pour un dict {vehicle_id: km}."""
|
||||||
total = 0.0
|
total = 0.0
|
||||||
for vehicle_id, km in km_by_vehicle.items():
|
for vehicle_id, km in km_by_vehicle.items():
|
||||||
vehicle = vehicles.get(vehicle_id, {})
|
vehicle = vehicles.get(vehicle_id, {})
|
||||||
@@ -14,12 +32,16 @@ def compute_co2_grams(km_by_vehicle: dict[str, int], vehicles: dict) -> float:
|
|||||||
return total
|
return total
|
||||||
|
|
||||||
|
|
||||||
def compute_frais_reels(total_km_voiture: float, tranches: list[dict]) -> float:
|
def compute_frais_reels(total_km_moteur: float, tranches: list[dict]) -> float:
|
||||||
if not tranches or total_km_voiture <= 0:
|
"""
|
||||||
|
Calcule les frais réels fiscaux selon le barème kilométrique.
|
||||||
|
km_max = 0 signifie "pas de limite" (dernière tranche).
|
||||||
|
"""
|
||||||
|
if not tranches or total_km_moteur <= 0:
|
||||||
return 0.0
|
return 0.0
|
||||||
for tranche in tranches:
|
for tranche in tranches:
|
||||||
km_max = tranche["km_max"]
|
km_max = tranche["km_max"]
|
||||||
if km_max == 0 or total_km_voiture <= km_max:
|
if km_max == 0 or total_km_moteur <= km_max:
|
||||||
return total_km_voiture * tranche["taux"] + tranche.get("forfait", 0)
|
return total_km_moteur * tranche["taux"] + tranche.get("forfait", 0)
|
||||||
last = tranches[-1]
|
last = tranches[-1]
|
||||||
return total_km_voiture * last["taux"] + last.get("forfait", 0)
|
return total_km_moteur * last["taux"] + last.get("forfait", 0)
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ from app.business.travel_calc import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
VEHICLES = {
|
VEHICLES = {
|
||||||
"voiture": {"co2_per_km": 142, "cv": 5},
|
"familiale": {"co2_per_km": 142, "cv": 5, "type": "moteur"},
|
||||||
"velo": {"co2_per_km": 0},
|
"citadine": {"co2_per_km": 0, "cv": 3, "type": "moteur"},
|
||||||
|
"velo": {"co2_per_km": 0, "type": "velo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
JOURNEYS = {
|
JOURNEYS = {
|
||||||
"voiture_seule": {"distances": {"voiture": 25}},
|
"moteur_seul": {"distances": {"moteur": 25}},
|
||||||
"voiture_velo": {"distances": {"voiture": 14, "velo": 8}},
|
"moteur_velo": {"distances": {"moteur": 14, "velo": 8}},
|
||||||
"velo_seul": {"distances": {"velo": 24}},
|
"velo_seul": {"distances": {"velo": 24}},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,20 +23,36 @@ TRANCHES_CV5 = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_compute_km_voiture_seule():
|
def test_compute_km_moteur_seul_avec_vehicule():
|
||||||
assert compute_km_for_entry("voiture_seule", JOURNEYS) == {"voiture": 25}
|
km = compute_km_for_entry("moteur_seul", JOURNEYS, "familiale")
|
||||||
|
assert km == {"familiale": 25}
|
||||||
|
|
||||||
|
|
||||||
def test_compute_km_voiture_velo():
|
def test_compute_km_moteur_velo_avec_vehicule():
|
||||||
assert compute_km_for_entry("voiture_velo", JOURNEYS) == {"voiture": 14, "velo": 8}
|
km = compute_km_for_entry("moteur_velo", JOURNEYS, "citadine")
|
||||||
|
assert km == {"citadine": 14, "velo": 8}
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_km_velo_seul():
|
||||||
|
km = compute_km_for_entry("velo_seul", JOURNEYS)
|
||||||
|
assert km == {"velo": 24}
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_km_sans_vehicule_moteur_ignore():
|
||||||
|
km = compute_km_for_entry("moteur_seul", JOURNEYS, None)
|
||||||
|
assert km == {}
|
||||||
|
|
||||||
|
|
||||||
def test_compute_km_no_journey():
|
def test_compute_km_no_journey():
|
||||||
assert compute_km_for_entry(None, JOURNEYS) == {}
|
assert compute_km_for_entry(None, JOURNEYS) == {}
|
||||||
|
|
||||||
|
|
||||||
def test_compute_co2_voiture():
|
def test_compute_co2_familiale():
|
||||||
assert compute_co2_grams({"voiture": 25}, VEHICLES) == 25 * 142
|
assert compute_co2_grams({"familiale": 25}, VEHICLES) == 25 * 142
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_co2_citadine_electrique():
|
||||||
|
assert compute_co2_grams({"citadine": 25}, VEHICLES) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_compute_co2_velo():
|
def test_compute_co2_velo():
|
||||||
|
|||||||
Reference in New Issue
Block a user