Files
redmine-reporter/redmine_reporter/formatters/html.py
Кокос Артем Николаевич 30310d614d Add HTML formatter
Closes #7
2026-01-26 12:57:33 +07:00

80 lines
3.1 KiB
Python

from typing import List, Dict, Any
from .base import Formatter
from ..types import ReportRow
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 = [
'<table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; font-family: Arial, sans-serif;">',
" <thead>",
" <tr>",
" <th>Наименование Проекта</th>",
" <th>Номер версии*</th>",
" <th>Задача</th>",
" <th>Статус Готовность*</th>",
" <th>Затрачено за отчетный период</th>",
" </tr>",
" </thead>",
" <tbody>",
]
for project, versions in projects.items():
total_project_rows = sum(len(tasks) for tasks in versions.values())
first_version_in_project = True
for version, task_rows in versions.items():
row_span_version = len(task_rows)
first_row_in_version = True
for r in task_rows:
lines.append(" <tr>")
# Ячейка "Проект" - только в первой строке проекта
if first_version_in_project and first_row_in_version:
lines.append(
f' <td rowspan="{total_project_rows}" style="vertical-align: top;">{project}</td>'
)
# Ячейка "Версия" - только в первой строке версии
if first_row_in_version:
lines.append(
f' <td rowspan="{row_span_version}" style="vertical-align: top;">{version}</td>'
)
first_row_in_version = False
# Остальные колонки
task_cell = f"{r['issue_id']}. {r['subject']}"
lines.append(f" <td>{task_cell}</td>")
lines.append(f" <td>{r['status_ru']}</td>")
lines.append(f" <td>{r['time_text']}</td>")
lines.append(" </tr>")
first_version_in_project = False
lines.append(" </tbody>")
lines.append("</table>")
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)