- GitLabClient: REST Events API z paginacją, pobieranie członków grupy - Aggregator: zliczanie commitów, MR, komentarzy per użytkownik - Exporter: generowanie pliku Excel (openpyxl) ze stylami - main.py: CLI (click) + .env support - README, .env.example, requirements.txt, .gitignore
104 lines
2.9 KiB
Python
104 lines
2.9 KiB
Python
"""
|
|
Eksporter — generuje plik Excel ze statystykami.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from datetime import date
|
|
|
|
from openpyxl import Workbook
|
|
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
|
from openpyxl.utils import get_column_letter
|
|
|
|
from aggregator import UserStats
|
|
|
|
|
|
HEADER_FILL = PatternFill(start_color="1F4E79", end_color="1F4E79", fill_type="solid")
|
|
HEADER_FONT = Font(color="FFFFFF", bold=True, size=11)
|
|
ALT_ROW_FILL = PatternFill(start_color="D6E4F0", end_color="D6E4F0", fill_type="solid")
|
|
|
|
THIN_BORDER = Border(
|
|
left=Side(style="thin"),
|
|
right=Side(style="thin"),
|
|
top=Side(style="thin"),
|
|
bottom=Side(style="thin"),
|
|
)
|
|
|
|
|
|
def export_to_excel(
|
|
stats: list[UserStats],
|
|
output_path: str,
|
|
group: str,
|
|
date_from: date,
|
|
date_to: date,
|
|
) -> None:
|
|
wb = Workbook()
|
|
ws = wb.active
|
|
ws.title = "Contributions"
|
|
|
|
# --- Tytuł ---
|
|
ws.merge_cells("A1:G1")
|
|
title_cell = ws["A1"]
|
|
title_cell.value = (
|
|
f"Raport aktywności GitLab — grupa: {group} "
|
|
f"({date_from} → {date_to})"
|
|
)
|
|
title_cell.font = Font(bold=True, size=13)
|
|
title_cell.alignment = Alignment(horizontal="center")
|
|
ws.row_dimensions[1].height = 24
|
|
|
|
# --- Nagłówki ---
|
|
headers = [
|
|
"Lp.",
|
|
"Imię i nazwisko",
|
|
"Username",
|
|
"Contributions (suma)",
|
|
"Commity",
|
|
"Merge Requesty",
|
|
"Komentarze",
|
|
]
|
|
ws.append([]) # pusty wiersz 2
|
|
ws.append(headers) # wiersz 3
|
|
|
|
header_row = 3
|
|
for col_idx, header in enumerate(headers, start=1):
|
|
cell = ws.cell(row=header_row, column=col_idx)
|
|
cell.font = HEADER_FONT
|
|
cell.fill = HEADER_FILL
|
|
cell.alignment = Alignment(horizontal="center", wrap_text=True)
|
|
cell.border = THIN_BORDER
|
|
|
|
# --- Dane ---
|
|
for i, user in enumerate(stats, start=1):
|
|
row_num = header_row + i
|
|
row_data = [
|
|
i,
|
|
user.name,
|
|
user.username,
|
|
user.total_contributions,
|
|
user.commits,
|
|
user.merge_requests,
|
|
user.comments,
|
|
]
|
|
ws.append(row_data)
|
|
|
|
fill = ALT_ROW_FILL if i % 2 == 0 else None
|
|
for col_idx in range(1, len(headers) + 1):
|
|
cell = ws.cell(row=row_num, column=col_idx)
|
|
cell.border = THIN_BORDER
|
|
cell.alignment = Alignment(horizontal="center")
|
|
if fill:
|
|
cell.fill = fill
|
|
# Imię/username — wyrównaj do lewej
|
|
if col_idx == 2:
|
|
cell.alignment = Alignment(horizontal="left")
|
|
|
|
# --- Szerokości kolumn ---
|
|
col_widths = [6, 30, 20, 22, 12, 18, 14]
|
|
for col_idx, width in enumerate(col_widths, start=1):
|
|
ws.column_dimensions[get_column_letter(col_idx)].width = width
|
|
|
|
# --- Zapis ---
|
|
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
|
|
wb.save(output_path)
|
|
print(f"✅ Zapisano: {output_path} ({len(stats)} użytkowników)")
|