feat: initial project structure
- 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
This commit is contained in:
103
exporter.py
Normal file
103
exporter.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
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)")
|
||||
Reference in New Issue
Block a user