Files
sufw-taetigkeitsnachweise/.copilot/PLAN.md
T
2026-06-24 08:35:31 +02:00

9.7 KiB
Raw Blame History

Ziel

Eine Python + Streamlit App für Windows, die aus einer Input-Excel-Datei (ein Sheet pro Monat mit Mitarbeiterdaten) und einem PDF-Template pro Mitarbeiter eine PDF-Datei generiert (eine Seite pro Monat, befüllt mit dessen Daten).

Ansatz: openpyxl für Input-Parsing + PyMuPDF (fitz) für PDF-Generierung + Streamlit-UI.

Hintergrund: Das ursprüngliche Excel-Template war teilweise schreibgeschützt und konnte nicht mit openpyxl befüllt werden. Daher wurde das Template als PDF exportiert. Im PDF wurden alle zu befüllenden Textstellen mit einem Platzhalter im Format {Feldname}_Field markiert (z. B. Antragsnummer_Field, Name_Field). Die App sucht nach diesen _Field-Markern und ersetzt sie durch die echten Daten.

Aufgabe

Erstelle eine Windows App in dessen Oberfläche aus folgenden Bestandteilen aufgebaut ist:

  • mittels einem DropDown-Menü kann eine Datei aus dem inputfolder gewählt werden
  • mittels einem DropDown-Menü kann ein PDF-Template aus dem Templatefolder gewählt werden
  • ein Button um den Vorgang zu starten

Die Funktion der App besteht darin, das Template-PDF mit Daten aus dem Input-File zu befüllen. Im Inputfile ist für alle Monate eines Jahres eine Liste aller Mitarbeitenden und in den Spalten alle Daten zur Befüllung des Templates.

Aufbau Input Datei

  • In der Input Datei ist für jeden Monat eines Jahres ein Sheet gespeichert.
  • In jedem Sheet befindet sich eine Tabelle (felder speichern in Input Schema json) mit Mitarbeitenden.
  • Für jeden Mitarbeitenden wird ein PDF erzeugt, das für jeden Monat eine Seite enthält, befüllt mit den Daten des Mitarbeiters für diesen Monat.

Aufbau PDF-Template

  • Das PDF-Template ist eine einseitige PDF-Datei, generiert aus der ursprünglichen XLSX-Vorlage.
  • Jede zu befüllende Textstelle enthält einen Platzhalter: den Feldnamen gefolgt von _Field (z. B. Antragsnummer_Field, Name_Field, Stellenanteil in %_Field, …).
  • Die App sucht im PDF nach allen _Field-Texten, ermittelt deren Position und Schriftgröße, und ersetzt sie durch die tatsächlichen Datenwerte.

README

In der README.md ist ein kleine Doku wie das Programm zu benutzen ist und welche Konfigurationsparameter es gibt.


Phasen-Plan

Phase 1: Projekt-Grundgerüst & Konfiguration

  1. requirements.txt befüllen — streamlit, openpyxl, PyMuPDF
  2. config/settings.ini befüllen — Pfade, Standardwerte
    • Abschnitte: [paths] (input_dir, template_dir, output_dir), [output] (filename_pattern → .pdf)
  3. config/input-fields.json Schema definieren — Spalten der Input-Tabelle mit ihren exakten Überschriften
    • JSON-Array mit column (Spaltenbuchstabe), field_name (exakte Überschrift aus der Excel-Tabelle), type (string|number|date), required (true|false)
  4. config/output-fields.json Mapping definieren — Welche Input-Felder in das PDF geschrieben werden
    • JSON-Array mit source_field (exakte Spaltenüberschrift aus der Input-Tabelle), format (optional, z. B. "dd.mm.yyyy")
    • Der Platzhalter im PDF ist immer {source_field}_Field – kein explizites target_cell mehr nötig

Phase 2: Core-Module (src/)

  1. src/__init__.py + src/models.py — Datenklassen
    • EmployeeRecord: name, vorname, nachname, antragsnummer, qualifikation, funktion, taetigkeit, stellenanteil, monat, jahr, … (Felder aus input-fields.json)
    • AppConfig: geladene settings.ini + input/output-schemas
  2. src/config.py — Konfigurations-Loader
    • load_settings(): liest config/settings.ini mit configparser
    • load_input_schema(): liest config/input-fields.json
    • load_output_mapping(): liest config/output-fields.json
    • get_available_input_files(): listet .xlsx-Dateien in input/
    • get_available_templates(): listet .pdf-Dateien in template/
  3. src/parser.py — Input-Datei einlesen (unverändert: openpyxl für XLSX-Input)
    • parse_input_file(filepath, schema): öffnet Workbook, iteriert über alle Sheets (Monate)
    • Extrahiert Monat/Jahr aus Sheet-Namen oder Sheet-Inhalt
    • Für jedes Sheet: liest Zeilen anhand des Schemas, erzeugt EmployeeRecord-Liste
    • Rückgabe: list[EmployeeRecord]

Phase 3: Writer & Validierung (PDF-basiert)

  1. src/writer.py — PDF-Output generieren (NEU: PyMuPDF)
    • generate_activity_reports(employee_records, template_path, mapping, config):
      • Pre-Scan: Öffnet das Template-PDF einmal und sucht nach allen _Field-Platzhaltern, ermittelt deren Position (bounding box) und Schriftgröße
      • Gruppiert Records nach Mitarbeiter
      • Für jeden Mitarbeiter:
        • Erstellt ein neues PDF
        • Für jeden Monats-Record: fügt eine Kopie der Template-Seite ein
        • Ersetzt alle _Field-Platzhalter durch die tatsächlichen Daten (redact + insert_text)
        • Speichert als {nachname}_{vorname}_Tätigkeitsnachweis.pdf in output/
  2. src/validator.py — Eingabevalidierung (angepasst für PDF)
    • validate_input_file(filepath, schema): unverändert (prüft XLSX-Input)
    • validate_template(template_path, mapping): prüft ob alle _Field-Platzhalter im PDF gefunden werden

Phase 4: Streamlit UI

  1. app.py — Streamlit-Oberfläche (angepasst für PDF-Templates)
    • Layout:
      • Titel + Beschreibung
      • st.selectbox für Input-Datei (aus input/-Folder)
        • Sofort bei Auswahl: Validierung + Parsing der Datei
        • Anzeige: Anzahl gefundener Mitarbeiter, Auflistung aller enthaltenen Antragsnummern
      • st.selectbox für PDF-Template (aus template/-Folder)
        • Sofort bei Auswahl: Validierung des PDF-Templates (Prüfung aller _Field-Marker)
        • Anzeige: Anzahl gefundener Platzhalter-Felder
      • Mitarbeiter-Liste (erscheint nach erfolgreicher Input-Validierung)
        • st.multiselect mit allen gefundenen Mitarbeiternamen, standardmäßig alle vorselektiert
      • st.button("Tätigkeitsnachweise generieren")
    • Bei Button-Click:
      1. Filtere Employee Records auf selektierte Mitarbeiter
      2. Generiere PDFs nur für selektierte Mitarbeiter und speichere in output/
      3. Zeige Erfolgsmeldung mit Liste der erstellten PDF-Dateien

Phase 5: Start-Skript & Doku

  1. start.bat — Windows Batch-Startdatei (unverändert)
  2. README.md aktualisieren — Vollständige Doku

Relevante Dateien (zu erstellen/ändern)

Datei Aktion
requirements.txt PyMuPDF hinzufügen
config/settings.ini filename_pattern auf .pdf ändern
config/output-fields.json target_cell entfernen (wird durch _Field-Marker ersetzt)
src/writer.py Komplett neu: PDF-basierte Generierung mit PyMuPDF
src/validator.py validate_template für PDF anpassen
src/config.py get_available_templates auf .pdf umstellen
app.py Template-Validierung für PDF anpassen
coldrun.py An PDF-Template anpassen
tests/test_e2e.py Tests für PDF-Output anpassen
.copilot/PLAN.md Dieser Plan – aktualisiert
.copilot/TASKS.md Aufgabenliste – aktualisiert
CHANGELOG.md Changelog – wird bei jedem Version-Build erweitert

Projektstruktur

/
├── .copilot/
│   ├── PLAN.md             ← diese Datei
│   └── TASKS.md            ← Aufgabenliste
├── input/
│   └── *.xlsx              ← Tabelle mit den Input-daten
├── config/
│   ├── settings.ini        ← Einstellungen der App
│   ├── input-fields.json   ← Schema der Inputdaten-Tabelle
│   └── output-fields.json  ← Mapping: Input-Feld → PDF-Platzhalter
├── output/                 ← Zielordner für generierte PDF-Dateien
├── template/
│   └── *.pdf               ← PDF-Template mit _Field-Platzhaltern
├── src/
│   ├── __init__.py
│   ├── models.py
│   ├── config.py
│   ├── parser.py
│   ├── writer.py           ← PDF-basierte Generierung (PyMuPDF)
│   └── validator.py
├── app.py                  ← Streamlit-App
├── coldrun.py              ← CLI Cold-Run
├── start.bat               ← Windows batch zum Start der App
├── README.md               ← README für Programmbenutzer
├── CHANGELOG.md            ← Changelog (wird bei jedem Version-Build erweitert)
└── requirements.txt        ← streamlit, openpyxl, PyMuPDF

Versionierung & Changelog

Immer wenn das Signal zum Build einer neuen Version gegeben wird (z. B. „Build Version X.Y“ oder „neue Version bauen“), wird das Changelog-Logfile (CHANGELOG.md im Projekt-Root) um die most recent changes erweitert. Der Eintrag enthält:

  • Versionsnummer (z. B. v1.2.0)
  • Datum des Builds
  • Neue Funktionen (Features)
  • Behobene Fehler (Bugfixes)
  • Sonstige Änderungen (z. B. Refactoring, Doku-Updates)

Der Changelog wird im Keep a Changelog-Format gepflegt und nach Semantic Versioning (MAJOR.MINOR.PATCH) versioniert.

Wichtig: Der Changelog-Eintrag wird vor dem eigentlichen Build-Vorgang erstellt, sodass die neue Version dokumentiert ist, bevor der Code ausgeliefert wird.


Verifikation

  1. Input-Datei-Analyse: 2025 JM.xlsx mit openpyxl öffnen, Sheet-Namen prüfen, Spaltenüberschriften validieren
  2. PDF-Template-Analyse: Tätigkeitsnachweise Stellenförderung.pdf mit PyMuPDF öffnen, alle _Field-Platzhalter suchen → mit output-fields.json abgleichen
  3. Unit-Test: App mit vorhandener Input-Datei und PDF-Template ausführen, prüfen ob Output-PDFs korrekt befüllt sind
  4. Edge Cases: Leere Input-Zeilen, fehlende Monate, Mitarbeiter ohne Vorname, Sonderzeichen in Namen, Umlaute im PDF