from html import escape from typing import Dict, List from ..types import ReportRow from .base import Formatter class HTMLFormatter(Formatter): """Форматтер для экспорта отчёта в HTML.""" def __init__(self, **_kwargs): super().__init__() def format(self, rows: List[ReportRow]) -> str: # Сгруппируем данные projects: Dict[str, Dict[str, List[ReportRow]]] = {} for r in rows: proj = r["project"] ver = r["version"] if proj not in projects: projects[proj] = {} if ver not in projects[proj]: projects[proj][ver] = [] projects[proj][ver].append(r) lines = [ '', " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", ] for project, versions in projects.items(): project_text = escape(project) total_project_rows = sum(len(tasks) for tasks in versions.values()) first_version_in_project = True for version, task_rows in versions.items(): version_text = escape(version) row_span_version = len(task_rows) first_row_in_version = True for r in task_rows: task_cell = escape(f"{r['issue_id']}. {r['subject']}") status_text = escape(r["status_ru"]) time_text = escape(r["time_text"]) lines.append(" ") # Ячейка "Проект" - только в первой строке проекта if first_version_in_project and first_row_in_version: lines.append( f' ' ) # Ячейка "Версия" - только в первой строке версии if first_row_in_version: lines.append( f' ' ) first_row_in_version = False # Остальные колонки lines.append(f" ") lines.append(f" ") lines.append(f" ") lines.append(" ") first_version_in_project = False lines.append(" ") lines.append("
Наименование ПроектаНомер версии*ЗадачаСтатус Готовность*Затрачено за отчетный период
{project_text}{version_text}{task_cell}{status_text}{time_text}
") return "\n".join(lines) def save(self, rows: List[ReportRow], output_path: str) -> None: content = self.format(rows) with open(output_path, "w", encoding="utf-8") as f: f.write(content)