53 lines
2.4 KiB
Python
53 lines
2.4 KiB
Python
from datetime import datetime
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
|
|
from ..summary import YearView
|
|
from .charts import change_bars, grouped_bars
|
|
from .i18n import T
|
|
|
|
TEMPLATES = Path(__file__).parent / "templates"
|
|
env = Environment(loader=FileSystemLoader(TEMPLATES), autoescape=select_autoescape(["html"]))
|
|
CSS = (TEMPLATES / "report.css").read_text()
|
|
|
|
|
|
def _exported() -> str:
|
|
return datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
|
|
|
|
def cost_report_html(view: YearView, lang: str, site: str | None = None, screen: bool = True) -> str:
|
|
t = T(lang, view.year.year, view.year.department.name)
|
|
cost_cats = view.with_lines("cost")
|
|
cats = []
|
|
for cv in cost_cats:
|
|
rows = [(lv.line.name, float(lv.figures.prior), float(lv.figures.adjusted)) for lv in cv.lines]
|
|
cats.append(SimpleNamespace(
|
|
name=cv.name(lang), count=len(cv.lines), totals=cv.totals,
|
|
chart=grouped_bars(rows, t.short_eur, lambda v: t.eur(v, 0))))
|
|
overview = grouped_bars([(c.name, float(c.totals.prior), float(c.totals.adjusted)) for c in cats], t.short_eur)
|
|
ranked = sorted([c for c in cats if c.totals.change_pct is not None],
|
|
key=lambda c: c.totals.change_pct, reverse=True)
|
|
change = change_bars([(c.name, float(c.totals.change_pct)) for c in ranked], lambda v: t.pct(v))
|
|
return env.get_template("cost_report.html").render(
|
|
t=t, title=t("cost_report_title"), year=view.year, site=site, cats=cats, costs=view.costs,
|
|
overview_chart=overview, change_chart=change, exported=_exported(), css=CSS, screen=screen)
|
|
|
|
|
|
def budget_html(view: YearView, lang: str, site: str | None = None, include_empty: bool = False) -> str:
|
|
t = T(lang, view.year.year, view.year.department.name)
|
|
cats = [SimpleNamespace(name=cv.name(lang), category=cv.category, lines=cv.lines, totals=cv.totals)
|
|
for cv in view.categories if cv.lines or include_empty]
|
|
# revenue first, as in the Budget IT sheet
|
|
cats.sort(key=lambda c: 0 if c.category.section == "revenue" else 1)
|
|
return env.get_template("budget.html").render(
|
|
t=t, title=t("budget_title"), year=view.year, site=site, cats=cats, costs=view.costs,
|
|
exported=_exported(), css=CSS)
|
|
|
|
|
|
def to_pdf(html: str) -> bytes:
|
|
from weasyprint import HTML # imported lazily: it loads system libraries
|
|
|
|
return HTML(string=html).write_pdf()
|