← Files VeraARCHIVED FILE

modules/management-control-pack/scripts/budget_presentation.py

5.54 KB · Oct 2, 2026 · 00:29 UTC

↓ Download file

"""Present precomputed budget comparisons through the shared reporting renderer."""

from __future__ import annotations

from collections import defaultdict
from collections.abc import Mapping
from decimal import Decimal
from html import escape
from pathlib import Path
from typing import Any

from management_report_copy import report_label
from reporting_table import render_reporting_table

__all__ = ["render_budget_comparisons"]

LINES = (
    ("revenue", "Ricavi", "Revenue"),
    ("cogs", "Costo del venduto", "Cost of sales"),
    ("gross_profit", "Margine lordo", "Gross profit"),
    ("operating_expense", "Costi operativi", "Operating expenses"),
    (
        "other_operating",
        "Altri proventi/oneri operativi",
        "Other operating income/expense",
    ),
    ("ebitda", "EBITDA", "EBITDA"),
    ("depreciation_amortization", "Ammortamenti", "Depreciation and amortization"),
    ("ebit", "EBIT", "EBIT"),
    ("interest", "Oneri finanziari", "Interest expense"),
    ("tax", "Imposte", "Tax"),
    ("other", "Altri proventi/oneri", "Other income/expense"),
    (
        "net_result",
        "Risultato netto sulle voci fornite",
        "Net result on supplied categories",
    ),
)
COSTS = {"cogs", "operating_expense", "depreciation_amortization", "interest", "tax"}
TOTALS = {"gross_profit", "ebitda", "ebit", "net_result"}


def render_budget_comparisons(pack: Mapping[str, Any]) -> str:
    """Select compiled views without changing numbers, signs, units or scales."""
    section = pack["sections"]["budget_variance"]
    language = pack.get("language", "en")

    def label(value: str) -> str:
        return report_label(value, language)

    grouped: dict[str, list[dict[str, Any]]] = defaultdict(list)
    for row in section.get("comparison_rows", []):
        grouped[row["view"]].append(row)
    if not grouped:
        return ""
    labels = {key: label(key) for key, _, _ in LINES}
    rendered_rows: dict[str, list[dict[str, Any]]] = {}
    for view, values in grouped.items():
        by_metric = {row["metric"]: row for row in values}
        rows = []
        for key, _, _ in LINES:
            row = by_metric[key]
            multiplier = -1 if key in COSTS else 1
            rows.append(
                {
                    "row_label": labels[key],
                    "baseline_value": str(Decimal(row["baseline"]) * multiplier),
                    "comparison_value": str(Decimal(row["comparison"]) * multiplier),
                    "absolute_variance": str(Decimal(row["variance"]) * multiplier),
                    "relative_variance": row["variance_pct"],
                    "favorable_direction": "lower" if key in COSTS else "higher",
                    "row_type": "subtotal" if key in TOTALS else "detail",
                }
            )
        rendered_rows[view] = rows
    scale_rows = [row for rows in rendered_rows.values() for row in rows]
    views = sorted(
        grouped, key=lambda view: (view != "total", view == "forecast", view)
    )
    titles = {
        "total": label("Actuals to ") + pack["reporting_period"]["cutoff"],
        "forecast": label("Full-period forecast"),
    }
    buttons = []
    figures = []
    for view in views:
        title = titles.get(view, view)
        scenario = grouped[view][0]["scenario"]
        buttons.append(
            f'<button type="button" data-budget-select="{escape(view)}" aria-controls="budget-{escape(view)}" aria-pressed="false">{escape(title)}</button>'
        )
        figure = render_reporting_table(
            row_header=label("Line item"),
            rows=rendered_rows[view],
            baseline_label="PL · " + label("Budget"),
            comparison_label=(
                "FC · " + label("Forecast")
                if scenario == "FC"
                else "AC · " + label("AC")
            ),
            entity_label=str(pack["entity"]),
            comparison_caption=title,
            metric=label("Profit and loss") + " · " + pack["currency"],
            source_label=label("Reviewed exports and mapping"),
            language=language,
            fragment=True,
            row_label_width=260,
            scale_rows=scale_rows,
            value_scale=1,
            value_width=112,
        )
        figures.append(
            f'<div id="budget-{escape(view)}" data-budget-view="{escape(view)}">{figure}</div>'
        )
    note = label(
        "Δ = scenario − budget. Costs are displayed positive; a reduction is favorable. Δ% = Δ / budget × 100; n/a for zero or negative bases. Views share units and scales."
    )
    if "forecast" in grouped:
        note += (
            label(" FC = actuals to cutoff + reviewed remaining-month estimates. ")
            + section["forecast_basis"]
        )
    limitations = "".join(
        f"<li>{escape(reason)}</li>" for reason in section.get("limitations", [])
    )
    assets = Path(__file__).resolve().parent.parent / "assets"
    css = (assets / "budget-report.css").read_text(encoding="utf-8")
    script = (assets / "budget-report.js").read_text(encoding="utf-8")
    heading = label("Actual and budget")
    if "forecast" in grouped:
        heading = label("Actual, budget and forecast")
    print_label = label("Print / PDF")
    scenarios = "PL · AC · FC" if "forecast" in grouped else "PL · AC"
    return f'<section class="budget-report"><style>{css}</style><p class="eyebrow">{scenarios}</p><h2>{heading}</h2><p>{escape(note)}</p><div class="budget-controls" hidden>{"".join(buttons)}<button type="button" data-budget-print>{print_label}</button></div>{"".join(figures)}<ul>{limitations}</ul><script>{script}</script></section>'

SHA-256: 643f526d3c6980fcefee72d3919c652da0b1016d6a0c9bfabff6de4b3a713706