from __future__ import annotations from datetime import datetime, timezone from typing import Any from fastapi.templating import Jinja2Templates def format_datetime(value: Any) -> str: """Render datetime values consistently for templates.""" if not isinstance(value, datetime): return "" if value.tzinfo is None: value = value.replace(tzinfo=timezone.utc) return value.strftime("%Y-%m-%d %H:%M UTC") def currency_display(value: Any, currency_code: str | None) -> str: """Format numeric values with currency context.""" if value is None: return "—" if isinstance(value, (int, float)): formatted_value = f"{value:,.2f}" else: formatted_value = str(value) if currency_code: return f"{currency_code} {formatted_value}" return formatted_value def format_metric(value: Any, metric_name: str, currency_code: str | None = None) -> str: """Format metrics according to their semantic type.""" if value is None: return "—" currency_metrics = { "npv", "inflows", "outflows", "net", "total_inflows", "total_outflows", "total_net", } if metric_name in currency_metrics and currency_code: return currency_display(value, currency_code) percentage_metrics = {"irr", "payback_period"} if metric_name in percentage_metrics: if isinstance(value, (int, float)): return f"{value:.2f}%" return f"{value}%" if isinstance(value, (int, float)): return f"{value:,.2f}" return str(value) def percentage_display(value: Any) -> str: """Format numeric values as percentages.""" if value is None: return "—" if isinstance(value, (int, float)): return f"{value:.2f}%" return f"{value}%" def period_display(value: Any) -> str: """Format period values in years.""" if value is None: return "—" if isinstance(value, (int, float)): if value == int(value): return f"{int(value)} years" return f"{value:.1f} years" return str(value) def register_common_filters(templates: Jinja2Templates) -> None: templates.env.filters["format_datetime"] = format_datetime templates.env.filters["currency_display"] = currency_display templates.env.filters["format_metric"] = format_metric templates.env.filters["percentage_display"] = percentage_display templates.env.filters["period_display"] = period_display __all__ = [ "format_datetime", "currency_display", "format_metric", "percentage_display", "period_display", "register_common_filters", ]