157 lines
7.7 KiB
Markdown
157 lines
7.7 KiB
Markdown
# Changelog
|
||
|
||
Alle nennenswerten Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
||
|
||
Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/),
|
||
und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||
|
||
---
|
||
|
||
## [1.3.2] – 2026-10-07
|
||
|
||
### Behoben
|
||
|
||
- EXE erkennt laufende Entwicklungsinstanz und fragt vor dem Neustart
|
||
|
||
---
|
||
|
||
## [1.3.1] – 2026-10-07
|
||
|
||
### Behoben
|
||
|
||
- Python script erkennt jetzt laufende Entwicklungsinstanz und fragt vor dem Neustart
|
||
|
||
---
|
||
|
||
## [1.3] – 2026-08-11
|
||
|
||
### Hinzugefügt
|
||
|
||
- **Monatsauswahl pro Mitarbeiter**: Tätigkeitsnachweise können nun für individuell gewählte Monate erzeugt werden.
|
||
- Die Monatsauswahl erscheint rechts neben der Mitarbeiterliste für die zuletzt angeklickte Person.
|
||
- Die Auswahl wird in Kurzform direkt hinter dem Namen angezeigt, z. B. `(Jan, Mär, Dez)`.
|
||
- Standardmäßig sind die letzten zwei vorhandenen Monate ausgewählt.
|
||
- Schaltflächen zum Auswählen bzw. Abwählen aller Monate ergänzen die Monatsliste.
|
||
|
||
- **Versionsprüfung**: Die App prüft beim Start im zentralen SMB-Verzeichnis auf neuere
|
||
`Tätigkeitsnachweis-Generator vX.Y.Z.zip`- und künftig auch `.exe`-Dateien.
|
||
|
||
- **Versionsanzeige**: Die aktuell installierte Programmversion wird dezent am unteren rechten Rand der App angezeigt.
|
||
|
||
### Geändert
|
||
|
||
- **Mitarbeiterauswahl**: Mitarbeiter sind nach dem Einlesen einer Input-Datei nicht mehr standardmäßig ausgewählt.
|
||
Die Buttons zum Auswählen bzw. Abwählen aller Mitarbeiter befinden sich direkt über der Mitarbeiterliste.
|
||
|
||
- **Update-Hinweis**: Bei einer neueren zentralen Version wird ein schwebender Hinweis oben rechts angezeigt,
|
||
einschließlich Schließen- und Ordner-Schaltfläche.
|
||
|
||
---
|
||
|
||
## [1.2.1] – 2026-06-30
|
||
|
||
### Behoben
|
||
|
||
- **Build-Pipeline**: fix broken server start and page call
|
||
|
||
---
|
||
|
||
## [1.2] – 2026-06-30
|
||
|
||
### Hinzugefügt
|
||
|
||
- **Build-Pipeline** (`1_build-pipeline/`): Skripte zum Erstellen einer standalone `.exe`:
|
||
- `build.bat` / `build.py`: Orchestrierter Build mit **Semantic Versioning** – liest aktuelle Version
|
||
aus `CHANGELOG.md`, bump't nach Wahl (major/minor/patch) und aktualisiert das Changelog automatisch
|
||
- `build.spec`: PyInstaller-Spec-Datei mit allen Hidden Imports für Streamlit, openpyxl und PyMuPDF
|
||
- `run.py`: Einstiegspunkt für die gebundelte `.exe` – setzt Pfade via `APP_BASE_DIR`,
|
||
startet den Streamlit-Server und öffnet den Browser
|
||
- Ausgabe nach `2_build/` mit fertiger Ordnerstruktur (`config/`, `input/`, `template/`, `output/`)
|
||
|
||
- **`app.py`** unterstützt jetzt `APP_BASE_DIR`-Umgebungsvariable für Pfadauflösung im gebundelten Modus
|
||
|
||
### Geändert
|
||
|
||
- **Statische Schriftgröße** (`src/writer.py`): Schriftgröße wird nicht mehr dynamisch aus dem PDF-Template extrahiert,
|
||
sondern statisch aus `settings.ini` (`[font]` → `fontsize`) gelesen, einheitlich für alle Felder.
|
||
`AppConfig` um `fontsize` erweitert, `config.py` lädt den Wert.
|
||
|
||
- **Autoskalierung entfernt** (`src/writer.py`): Die automatische Schriftverkleinerung für lange Texte
|
||
(`Qualifikation_Field`, `Funktion_Field`) wurde ersatzlos gestrichen – alle Texte haben exakt dieselbe Größe.
|
||
|
||
- **Vertikale Textzentrierung** (`src/writer.py`): Einzeilige Felder werden jetzt vertikal mittig im
|
||
Marker-Rechteck platziert. Mehrzeilige Felder (`Tätigkeiten_Field`, `Dienstreisen_Field`) bleiben
|
||
oben ausgerichtet.
|
||
|
||
- **Doppelte Felder unterstützt** (`src/writer.py`): `Datum_Field` und andere Marker, die mehrfach im
|
||
PDF-Template vorkommen, werden jetzt alle mit demselben Wert befüllt.
|
||
|
||
- **Stellenanteil-Formatierung** (`src/writer.py`): `Stellenanteil in %` wird mit deutschem Dezimalkomma
|
||
und zwei Nachkommastellen ausgegeben (z. B. `75` → `75,00`).
|
||
|
||
---
|
||
|
||
## [1.1] – 2026-06-24
|
||
|
||
### Hinzugefügt
|
||
|
||
- **Streamlit-Web-UI** (`app.py`) mit:
|
||
- Dropdown zur Auswahl der Input-Datei (`.xlsx`) aus dem `input/`-Ordner – mit Sofort-Validierung und Anzeige von Mitarbeiteranzahl, Antragsnummern und Einträgen pro Monat
|
||
- Dropdown zur Auswahl des PDF-Templates aus dem `template/`-Ordner – mit Sofort-Validierung und Anzeige gefundener `_Field`-Platzhalter
|
||
- Mitarbeiter-Multiselect-Liste mit „Alle auswählen“ / „Keine auswählen“-Buttons
|
||
- „Tätigkeitsnachweise generieren“-Button mit Fortschrittsanzeige
|
||
- Session-State-Caching für Validierung und Parsing (kein erneutes Einlesen bei UI-Reruns)
|
||
- Erfolgsmeldung mit Liste generierter Dateien und Button zum Öffnen des Output-Ordners
|
||
|
||
- **PDF-basierte Generierung** (`src/writer.py`) via PyMuPDF (fitz):
|
||
- Pre-Scan aller `_Field`-Platzhalter im Template-PDF über **alle Seiten**
|
||
- Automatische Erkennung von Position (Bounding Box) und Schriftgröße jedes Platzhalters
|
||
- Redact + Insert-Text-Verfahren: Platzhalter werden geschwärzt und durch echte Daten ersetzt
|
||
- Unterstützung für **mehrseitige Templates** (z. B. 2 Seiten pro Monat)
|
||
- **Mehrzeilige Textboxen** (`Tätigkeiten_Field`, `Dienstreisen_Field`) mit automatischem Wortumbruch
|
||
- **Automatische Schriftgrößen-Anpassung** bei langen Texten in Qualifikation und Funktion (Autoscale)
|
||
- Prozentwerte werden als Ganzzahl ohne `%`-Zeichen ausgegeben
|
||
- Datumsformat `dd.mm.yyyy` wird automatisch aus dem Monatsfeld (`MM.JJ`) berechnet
|
||
- Ort standardmäßig „Dresden“
|
||
- Dateiname: `{Nachname}_{Vorname}_Tätigkeitsnachweis.pdf`
|
||
|
||
- **Input-Parsing** (`src/parser.py`):
|
||
- Einlesen von `.xlsx`-Dateien mit openpyxl – ein Sheet pro Monat
|
||
- Monats-Sheet-Erkennung per Wildcard-Pattern (`* 20??`)
|
||
- Prozentwert-Konvertierung: Excel-Prozentwerte (0.5 → 50) oder Ganzzahlen (50 → 50)
|
||
- Automatisches Überspringen leerer Zeilen (Name oder Antragsnummer fehlt)
|
||
- Gruppierung der Records nach Mitarbeitername (`group_by_employee`)
|
||
- Hilfsfunktionen: `get_unique_antragsnummern`, `get_unique_employees`
|
||
|
||
- **Validierung** (`src/validator.py`):
|
||
- Input-Datei: Prüft Existenz, Spaltenüberschriften (gegen `input-fields.json`), Datenzeilen pro Monats-Sheet
|
||
- Input-Daten: Erkennt leere Pflichtfelder pro Person und meldet betroffene Namen
|
||
- PDF-Template: Sucht alle `_Field`-Platzhalter im PDF und meldet fehlende
|
||
- Nicht-Monats-Sheets (z. B. „Alle Rollen“) werden ignoriert
|
||
|
||
- **Konfigurationsdateien** (`config/`):
|
||
- `settings.ini`: Pfade für Input/Template/Output, Dateinamen-Pattern, Monats-Sheet-Pattern, Skip-Optionen
|
||
- `input-fields.json`: Spaltenschema der Input-Tabelle (9 Felder: ID, Kommentar, Antragsnummer, Name, Qualifikation, Funktion, Stellenanteil in %, Monat, Tätigkeit)
|
||
- `output-fields.json`: Mapping Input-Feld → `_Field`-Platzhalter im PDF (8 Felder)
|
||
|
||
- **Datenmodell** (`src/models.py`):
|
||
- `EmployeeRecord`: Dataclass für eine Mitarbeiter-Zeile mit `month_index`- und `year`-Properties
|
||
- `FieldSchema`, `OutputMapping`, `AppConfig`, `ValidationResult`
|
||
|
||
- **Cold Run** (`coldrun.py`): Headless-Generierung für die erste Person ohne GUI, automatisch mit erster Input- und Template-Datei
|
||
|
||
- **Start-Skripte**: `start.bat` (Windows), `start.sh` / `start.command` (macOS/Linux)
|
||
|
||
- **End-to-End-Tests** (`tests/test_e2e.py`):
|
||
- pytest-basiert mit realer Input-Datei (`2025 JM.xlsx`) und realem PDF-Template
|
||
- Prüft: 168 Datensätze, 19 Personen, 12 Monate
|
||
- Validiert Output-PDF: Seitenanzahl (24 Seiten = 12 × 2), Inhalte (Antragsnummer, Name, Stellenanteil, Qualifikation, Monat, Funktion, Tätigkeit), keine verbliebenen `_Field`-Platzhalter
|
||
|
||
- **README.md**: Vollständige Dokumentation zu Setup, Bedienung, Konfiguration, Cold Run und Tests
|
||
|
||
### Geändert
|
||
|
||
- Template-Format von `.xlsx` auf **PDF** umgestellt (ursprüngliches Excel-Template war schreibgeschützt)
|
||
- `config/output-fields.json`: `target_cell` entfernt – Mapping erfolgt jetzt über `_Field`-Platzhalter im PDF
|
||
- `src/config.py`: `get_available_templates` filtert jetzt `.pdf`-Dateien
|