"""Template: age-life depreciation with year-by-year curve.""" from __future__ import annotations from typing import Any from app.tools.coerce import num, pct def _f(p: dict[str, Any], key: str, default: float) -> float: """Tolerant numeric param; keys ending in `_pct` / starting with `taux` are ratios.""" raw = p.get(key) v = pct(raw, None) if (key.endswith("_pct") or key.startswith("taux")) else num(raw, None) return float(default) if v is None else v def build(p: dict[str, Any]) -> dict[str, Any]: cn = _f(p, "cout_neuf", 450000) age_eff = _f(p, "age_effectif", 12) dve = _f(p, "duree_vie_economique", 60) inputs = [ {"cell": "B4", "label": "Coût neuf C_N ($)", "value": cn, "format": "currency", "name": "Cout_Neuf"}, {"cell": "B5", "label": "Âge effectif A_e (ans)", "value": age_eff, "format": "number", "name": "Age_Effectif"}, {"cell": "B6", "label": "Durée de vie économique DVE (ans)", "value": dve, "format": "number", "name": "DVE"}, ] results = { "anchor": "A9", "columns": [{"header": "Résultat", "type": "text"}, {"header": "Valeur", "type": "currency"}], "rows": [ ["Taux de dépréciation (A_e / DVE)", "=B5/B6"], ["Dépréciation D ($)", "=B4*B5/B6"], ["Coût déprécié ($)", "=B4-B11"], ["Durée de vie restante (ans)", "=B6-B5"], ], "row_formats": {0: "percent", 3: "number"}, } years = int(min(dve, 80)) curve_rows = [[y, f"=MIN(1,{'A'}{16 + y}/$B$6)", f"=$B$4*(1-B{16 + y})"] for y in range(0, years + 1)] curve = { "anchor": "A15", "columns": [{"header": "Âge (ans)", "type": "integer"}, {"header": "Taux de dépréciation", "type": "percent"}, {"header": "Coût déprécié ($)", "type": "currency"}], "rows": curve_rows, } return { "filename": p.get("filename", "depreciation_age_vie.xlsx"), "style": "uqo", "sheets": [{ "name": "Âge-vie", "title": "Dépréciation par la méthode âge-vie", "inputs": inputs, "tables": [results, curve], "charts": [{"type": "line", "title": "Courbe âge-vie du coût déprécié", "categories_range": f"A16:A{16 + years}", "values_range": f"C16:C{16 + years}", "anchor": "E9"}], "notes": ["D = (A_e / DVE) × C_N ; la méthode suppose une dépréciation linéaire.", "L'âge effectif reflète l'état observé, pas l'âge chronologique."], }], }