SFM/app/pipeline/protocol.py
2026-06-22 07:25:27 +03:00

92 lines
2.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Iterable
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, PatternFill
from openpyxl.utils import get_column_letter
@dataclass
class ProtocolRow:
file_name: str
status: str
message: str
operations_total: int
rows_written: int
launcher: str
processed_at: datetime
def write_protocol(rows: Iterable[ProtocolRow], destination: Path) -> None:
row_list = list(rows)
workbook = Workbook()
details = workbook.active
details.title = "Протокол"
details.freeze_panes = "A2"
columns = [
"Имя файла",
"Статус",
"Комментарий",
"Операций",
"Строк отчета",
"Запустил",
"Время обработки",
]
_write_header(details, columns)
for row_index, row in enumerate(row_list, start=2):
values = [
row.file_name,
row.status,
row.message,
row.operations_total,
row.rows_written,
row.launcher,
row.processed_at.strftime("%Y-%m-%d %H:%M:%S"),
]
for col_index, value in enumerate(values, start=1):
details.cell(row=row_index, column=col_index, value=value)
_auto_width(details, columns)
_write_summary(workbook, row_list)
destination.parent.mkdir(parents=True, exist_ok=True)
workbook.save(destination)
def _write_summary(workbook: Workbook, rows: list[ProtocolRow]) -> None:
summary = workbook.create_sheet("Итог")
total = len(rows)
success = sum(1 for row in rows if row.status == "success")
partial = sum(1 for row in rows if row.status == "partial")
errors = sum(1 for row in rows if row.status == "error")
metrics = [
("Всего файлов", total),
("Успешно", success),
("Частично", partial),
("Ошибки", errors),
]
for index, (name, value) in enumerate(metrics, start=1):
summary.cell(row=index, column=1, value=name).font = Font(bold=True)
summary.cell(row=index, column=2, value=value)
summary.column_dimensions[get_column_letter(1)].width = 24
summary.column_dimensions[get_column_letter(2)].width = 14
def _write_header(sheet, columns: list[str]) -> None:
fill = PatternFill(start_color="D9E1F2", end_color="D9E1F2", fill_type="solid")
for index, name in enumerate(columns, start=1):
cell = sheet.cell(row=1, column=index, value=name)
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal="center", vertical="center")
cell.fill = fill
def _auto_width(sheet, columns: list[str]) -> None:
for index, name in enumerate(columns, start=1):
width = max(14, min(70, len(name) + 6))
sheet.column_dimensions[get_column_letter(index)].width = width