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

184 lines
9.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`)
5. **`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
6. **`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/`
7. **`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)
8. **`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/`
9. **`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
10. **`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
11. **`start.bat`** — Windows Batch-Startdatei (unverändert)
12. **`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](https://keepachangelog.com/)-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
```