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:
2026-03-04 18:27:01 +00:00
commit 066539c89c
8 changed files with 484 additions and 0 deletions

103
exporter.py Normal file
View 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)")