diff --git a/.github/copilot-tasks.md b/.github/copilot-tasks.md index aa222bf..a43e8ed 100644 --- a/.github/copilot-tasks.md +++ b/.github/copilot-tasks.md @@ -67,10 +67,10 @@ Projekt vollstaendig umsetzen: aus PS_PW.xlsx und Stellenbeschreibungen.xlsx mon - [x] Pflicht-Zielzellen vollstaendig konfiguriert ## Phase 6 - Ausgabeerzeugung -- [ ] T11: Template-Verarbeitung bauen - - [ ] Template-Workbook laden - - [ ] Sheet pro aktiver Zuordnung klonen - - [ ] Inhalte assignment-spezifisch in Zielzellen schreiben +- [x] T11: Template-Verarbeitung bauen + - [x] Template-Workbook laden + - [x] Sheet pro aktiver Zuordnung klonen + - [x] Inhalte assignment-spezifisch in Zielzellen schreiben - [ ] T12: Dateinamen und Speichern - [ ] Muster: `Taetigkeitsnachweis_YYYY_MM_Vorname_Nachname.xlsx` - [ ] Pro Mitarbeiter genau eine Datei pro Monat erzeugen @@ -111,4 +111,4 @@ Projekt vollstaendig umsetzen: aus PS_PW.xlsx und Stellenbeschreibungen.xlsx mon 8. T15 -> T16 -> T17 ## Aktueller Startpunkt -- [ ] Naechste aktive Aufgabe: T11 (Template-Verarbeitung bauen) +- [ ] Naechste aktive Aufgabe: T12 (Dateinamen und Speichern) diff --git a/src/taetigkeitsnachweis/writer.py b/src/taetigkeitsnachweis/writer.py index d0b44b9..9a6e24b 100644 --- a/src/taetigkeitsnachweis/writer.py +++ b/src/taetigkeitsnachweis/writer.py @@ -1 +1,96 @@ """Template-based output workbook writer.""" + +from __future__ import annotations + +from collections import defaultdict +from datetime import date +from pathlib import Path +from typing import Any + +from openpyxl import Workbook, load_workbook + +from .models import MatchedAssignment + + +def _split_name_for_filename(name: str) -> tuple[str, str]: + cleaned = str(name or "").strip() + if "," in cleaned: + last_name, first_name = [part.strip() for part in cleaned.split(",", 1)] + return first_name or "Unknown", last_name or "Unknown" + + parts = cleaned.split() + if len(parts) >= 2: + return parts[0], parts[-1] + if len(parts) == 1: + return parts[0], "Unknown" + return "Unknown", "Unknown" + + +def _normalize_sheet_title(raw_title: str, fallback_index: int) -> str: + cleaned = (raw_title or "").strip().replace("[", "(").replace("]", ")") + if not cleaned: + cleaned = f"Assignment_{fallback_index}" + return cleaned[:31] + + +def _set_target_value(worksheet: Any, target_cell: str, value: Any) -> None: + if not target_cell: + return + worksheet[target_cell] = value + + +def build_employee_workbooks( + config: dict[str, Any], + matched_assignments: list[MatchedAssignment], + report_month: int, + report_year: int, + project_root: Path, +) -> dict[str, Workbook]: + paths_cfg = config["paths"] + files_cfg = config["files"] + output_cfg = config["output"] + targets = config.get("template_targets", {}) + + template_path = ( + project_root + / paths_cfg["template_dir"] + / files_cfg["template_workbook"] + ) + + assignments_by_employee: dict[str, list[MatchedAssignment]] = defaultdict(list) + for assignment in matched_assignments: + assignments_by_employee[assignment.allocation.employee_name].append(assignment) + + workbooks: dict[str, Workbook] = {} + month_label = f"{report_month:02d}/{report_year}" + today_label = date.today().strftime("%d.%m.%Y") + + for employee_name, assignments in assignments_by_employee.items(): + workbook = load_workbook(template_path) + base_sheet = workbook.worksheets[0] + + for index, assignment in enumerate(assignments, start=1): + if index == 1: + sheet = base_sheet + else: + sheet = workbook.copy_worksheet(base_sheet) + + sheet_name_pattern = output_cfg.get("sheet_name_pattern", "{index}_{funktion}") + raw_sheet_name = sheet_name_pattern.format( + index=index, + funktion=assignment.masterdata.funktion, + ) + sheet.title = _normalize_sheet_title(raw_sheet_name, index) + + _set_target_value(sheet, targets.get("antragsnummer", ""), assignment.masterdata.antragsnummer) + _set_target_value(sheet, targets.get("name_vorname", ""), assignment.allocation.employee_name) + _set_target_value(sheet, targets.get("qualifikation", ""), assignment.masterdata.qualifikation) + _set_target_value(sheet, targets.get("funktion", ""), assignment.masterdata.funktion) + _set_target_value(sheet, targets.get("taetigkeiten", ""), assignment.masterdata.taetigkeit) + _set_target_value(sheet, targets.get("reporting_month_label", ""), month_label) + _set_target_value(sheet, targets.get("foerderquote", ""), f"{assignment.foerderquote_percent:.2f} %") + _set_target_value(sheet, targets.get("generated_on", ""), today_label) + + workbooks[employee_name] = workbook + + return workbooks