1073 lines
22 KiB
Markdown
1073 lines
22 KiB
Markdown
# Firefly Import Preprocessor - Dokumentation
|
|
|
|
**Version:** 1.0.0
|
|
**Datum:** 10. Dezember 2025
|
|
**Status:** Production Ready
|
|
|
|
---
|
|
|
|
## 📋 Inhaltsverzeichnis
|
|
|
|
1. [Überblick](#überblick)
|
|
2. [Installation & Setup](#installation--setup)
|
|
3. [Schnellstart](#schnellstart)
|
|
4. [Konfiguration](#konfiguration)
|
|
5. [Transformationstypen](#transformationstypen)
|
|
6. [CLI-Referenz](#cli-referenz)
|
|
7. [Debug-Modus](#debug-modus)
|
|
8. [Firefly III Integration](#firefly-iii-integration)
|
|
9. [Architektur](#architektur)
|
|
10. [Fehlerbehandlung](#fehlerbehandlung)
|
|
|
|
---
|
|
|
|
## Überblick
|
|
|
|
Der **Firefly Import Preprocessor** ist ein produktionsreifer PHP-Preprocessor für Banken-CSV-Exportdateien. Er transformiert Bankdaten in ein standardisiertes Format und kann sie optional in Firefly III importieren.
|
|
|
|
### Kernfeatures
|
|
|
|
✅ **Vollständige CSV-Transformation** mit komplexen Pipelines
|
|
✅ **Metadaten-Extraktion** mit Regex (IBAN, Währung, Kontoname)
|
|
✅ **11 Transformationstypen** für flexible Datenverarbeitung
|
|
✅ **Firefly III Integration** mit Docker-Support
|
|
✅ **Debug-Modus** für Transparenz bei Verarbeitung
|
|
✅ **Production Ready** mit vollständiger Fehlerbehandlung
|
|
✅ **Zero Dependencies** für Core-Funktionalität
|
|
|
|
### Workflow
|
|
|
|
```
|
|
Input CSV
|
|
↓
|
|
Metadaten extrahieren (Regex)
|
|
↓
|
|
Datenzeilen transformieren (Pipeline)
|
|
↓
|
|
Output CSV schreiben
|
|
↓
|
|
[Optional] In Firefly III importieren
|
|
```
|
|
|
|
---
|
|
|
|
## Installation & Setup
|
|
|
|
### Voraussetzungen
|
|
|
|
- PHP 8.1+
|
|
- Composer (empfohlen)
|
|
- [Optional] Docker für Firefly III Integration
|
|
|
|
### Installation
|
|
|
|
```bash
|
|
# 1. Repository clonen/kopieren
|
|
cd ff-imp-preprocessor
|
|
|
|
# 2. Abhängigkeiten installieren (optional)
|
|
composer install
|
|
|
|
# 3. Konfiguration erstellen
|
|
cp config/config.example.json config/config.json
|
|
# Bearbeite config/config.json mit deinen Einstellungen
|
|
|
|
# 4. Directories erstellen
|
|
mkdir -p config/import/{source,output,archive,error}
|
|
chmod 755 config/import/{source,output,archive,error}
|
|
|
|
# 5. Test durchführen
|
|
php bin/transformer.php validate config/config.json input.csv
|
|
```
|
|
|
|
---
|
|
|
|
## Schnellstart
|
|
|
|
### 1. Konfiguration anpassen
|
|
|
|
Bearbeite `config/config.json` und stelle sicher, dass die Extraction-Rules zu deinem CSV-Format passen:
|
|
|
|
```json
|
|
{
|
|
"metadata": {
|
|
"extractionRules": [
|
|
{
|
|
"name": "account_iban",
|
|
"lineNumber": 2,
|
|
"regex": "IBAN:\\s*([A-Z0-9 ]+)",
|
|
"captureGroup": 1
|
|
}
|
|
]
|
|
},
|
|
"csvStructure": {
|
|
"headerLine": 5,
|
|
"delimiter": ";",
|
|
"encoding": "UTF-8"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. CSV validieren
|
|
|
|
```bash
|
|
php bin/transformer.php validate config/config.json input.csv
|
|
```
|
|
|
|
Output:
|
|
```
|
|
✓ CSV ist valid
|
|
IBAN: CH9300762011623852957
|
|
Währung: CHF
|
|
Zeilen: 150
|
|
```
|
|
|
|
### 3. Transformation durchführen
|
|
|
|
```bash
|
|
php bin/transformer.php process config/config.json input.csv
|
|
|
|
# Mit Debug-Modus für Fehlersuche
|
|
php bin/transformer.php process config/config.json input.csv --debug
|
|
```
|
|
|
|
### 4. Output prüfen
|
|
|
|
```bash
|
|
# Transformierte Datei
|
|
cat config/import/output/transformed.csv
|
|
|
|
# Oder mit Debug-Ausgabe
|
|
php bin/transformer.php test config/config.json input.csv --debug
|
|
# Zeigt max. 10 transformierte Zeilen und Debug-Logs
|
|
```
|
|
|
|
---
|
|
|
|
## Konfiguration
|
|
|
|
### config.json Struktur
|
|
|
|
#### `metadata` - Metadaten-Extraktion
|
|
|
|
```json
|
|
{
|
|
"metadata": {
|
|
"extractionRules": [
|
|
{
|
|
"name": "account_iban",
|
|
"lineNumber": 2,
|
|
"regex": "IBAN:\\s*([A-Z0-9 ]+)",
|
|
"captureGroup": 1
|
|
},
|
|
{
|
|
"name": "currency_code",
|
|
"lineNumber": 3,
|
|
"regex": "Währung:\\s*([A-Z]{3})",
|
|
"captureGroup": 1
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `name` | string | Name der Metadaten-Variable (verwendet in constantvalue) |
|
|
| `lineNumber` | int | Zeilennummer in CSV (1-basiert, menschenlesbar) |
|
|
| `regex` | string | Regex-Pattern zur Extraktion (ohne Delimiter) |
|
|
| `captureGroup` | int | Nummer der Klammer-Gruppe (0=komplett, 1=erste Klammer, etc.) |
|
|
|
|
**Beispiel Regex:**
|
|
- Pattern: `IBAN:\s*([A-Z0-9 ]+)`
|
|
- Input: `IBAN: CH93 0076 2011 6238 5295 7`
|
|
- Capture Group 1: `CH93 0076 2011 6238 5295 7`
|
|
|
|
#### `csvStructure` - CSV-Format
|
|
|
|
```json
|
|
{
|
|
"csvStructure": {
|
|
"headerLine": 5,
|
|
"delimiter": ";",
|
|
"encoding": "UTF-8",
|
|
"hasBom": false
|
|
}
|
|
}
|
|
```
|
|
|
|
| Feld | Typ | Default | Beschreibung |
|
|
|------|-----|---------|-------------|
|
|
| `headerLine` | int | 5 | Zeilennummer der Header (1-basiert) |
|
|
| `delimiter` | string | `;` | CSV-Delimiter |
|
|
| `encoding` | string | `UTF-8` | Zeichenkodierung (UTF-8, ISO-8859-1, CP1252) |
|
|
| `hasBom` | bool | false | Hat die Datei BOM (Byte Order Mark)? |
|
|
|
|
#### `columnTransformations` - Spalten-Transformationen
|
|
|
|
```json
|
|
{
|
|
"columnTransformations": [
|
|
{
|
|
"sourceColumn": "Buchungsdatum",
|
|
"transformations": [
|
|
{
|
|
"type": "dateformat",
|
|
"fromFormat": "d.m.Y",
|
|
"toFormat": "Y-m-d"
|
|
}
|
|
],
|
|
"outputColumn": "date",
|
|
"outputAction": "overwrite"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**outputAction:**
|
|
- `overwrite` - Überschreibe sourceColumn
|
|
- `create` - Erstelle neue Spalte (für Regex-Extract, Split, etc.)
|
|
|
|
#### `directories` - Dateisystem
|
|
|
|
```json
|
|
{
|
|
"directories": {
|
|
"source": "/opt/ff-imp-preprocessor/import/source",
|
|
"output": "/opt/ff-imp-preprocessor/import/output",
|
|
"archive": "/opt/ff-imp-preprocessor/import/archive",
|
|
"error": "/opt/ff-imp-preprocessor/import/error"
|
|
}
|
|
}
|
|
```
|
|
|
|
| Feld | Beschreibung |
|
|
|------|-------------|
|
|
| `source` | Eingabe-Verzeichnis |
|
|
| `output` | Ausgabe-Verzeichnis |
|
|
| `archive` | Archiv für verarbeitete Dateien |
|
|
| `error` | Error-Verzeichnis für ungültige Dateien |
|
|
|
|
#### `fireflyImport` - Firefly III Integration
|
|
|
|
```json
|
|
{
|
|
"fireflyImport": {
|
|
"jsonConfig": "/opt/firefly/import-config.json",
|
|
"importerCommand": "docker exec -it firefly-importer php artisan importer:import",
|
|
"autoImport": false,
|
|
"deleteAfterImport": false,
|
|
"timeout": 300,
|
|
"environment": {
|
|
"FIREFLY_III_URL": "https://your-firefly.com",
|
|
"FIREFLY_III_ACCESS_TOKEN": "your-token-here"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Transformationstypen
|
|
|
|
Es gibt **13 unterstützte Transformationstypen**, die als Pipeline kombiniert werden können:
|
|
|
|
### 1. **trim** - Leerzeichen entfernen
|
|
|
|
Entfernt Leerzeichen am Anfang und Ende.
|
|
|
|
```json
|
|
{
|
|
"type": "trim"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: ` Coop Pronto `
|
|
- Output: `Coop Pronto`
|
|
|
|
---
|
|
|
|
### 2. **lowercase** - Zu Kleinbuchstaben
|
|
|
|
Wandelt in Kleinbuchstaben um (UTF-8 safe).
|
|
|
|
```json
|
|
{
|
|
"type": "lowercase"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `COOP PRONTO CHUR`
|
|
- Output: `coop pronto chur`
|
|
|
|
---
|
|
|
|
### 3. **uppercase** - Zu Grossbuchstaben
|
|
|
|
Wandelt in Grossbuchstaben um (UTF-8 safe).
|
|
|
|
```json
|
|
{
|
|
"type": "uppercase"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `Coop Pronto Chur`
|
|
- Output: `COOP PRONTO CHUR`
|
|
|
|
---
|
|
|
|
### 4. **ucwordsfirst** - Grossschreibung nach Trennzeichen
|
|
|
|
Grossschreibt ersten Buchstaben nach Worttrennzeichen.
|
|
|
|
```json
|
|
{
|
|
"type": "ucwordsfirst"
|
|
}
|
|
```
|
|
|
|
**Beispiele:**
|
|
- `COOP PRONTO CHUR` → `Coop Pronto Chur`
|
|
- `migros-rail city` → `Migros-Rail City`
|
|
- `O'NEILL STORE` → `O'Neill Store`
|
|
- `SAINT-JEAN-DE-MAURIENNE` → `Saint-Jean-De-Maurienne`
|
|
|
|
Trennzeichen: Leerzeichen, Bindestrich, Apostroph, Slash, Punkt, Komma, Semikolon, Doppelpunkt, Klammern.
|
|
|
|
---
|
|
|
|
### 5. **replace** - String-Replacement
|
|
|
|
Ersetzt Substring durch anderen String (case-sensitive).
|
|
|
|
```json
|
|
{
|
|
"type": "replace",
|
|
"search": " ",
|
|
"replace": " "
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `Coop Pronto` (2 Leerzeichen)
|
|
- Output: `Coop Pronto` (1 Leerzeichen)
|
|
|
|
---
|
|
|
|
### 6. **split** - Spalte teilen
|
|
|
|
Teilt einen Wert bei Delimiter und behält einen definierten Teil.
|
|
|
|
```json
|
|
{
|
|
"type": "split",
|
|
"delimiter": ";",
|
|
"part": 0
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `Coop Pronto Chur;7007 Chur`
|
|
- Config: `delimiter=";"`, `part=0`
|
|
- Output: `Coop Pronto Chur`
|
|
|
|
---
|
|
|
|
### 7. **regex** - Regex-Ersetzung
|
|
|
|
Ersetzt Teile des Strings per regulärem Ausdruck. Nutzt PHP `preg_replace`.
|
|
|
|
```json
|
|
{
|
|
"type": "regex",
|
|
"pattern": "^(.*?);.*$",
|
|
"replace": "$1"
|
|
}
|
|
```
|
|
|
|
**Beispiel — mit Match:**
|
|
- Input: `Friis, Daniela Silvia; Zahlung UBS TWINT`
|
|
- Pattern: `^(.*?);.*$`, Replace: `$1`
|
|
- Output: `Friis, Daniela Silvia`
|
|
|
|
**Beispiel — kein Match (pass-through):**
|
|
- Input: `Coop Pronto Chur` (kein Semikolon)
|
|
- Output: `Coop Pronto Chur` ← Wert bleibt **unverändert**
|
|
|
|
**Beispiel — Pattern ohne Anchors (ersetzt nur den gematchten Teil):**
|
|
- Input: `Zahlung UBS TWINT; Referenz 12345`
|
|
- Pattern: `UBS TWINT`, Replace: `TWINT`
|
|
- Output: `Zahlung TWINT; Referenz 12345`
|
|
|
|
**Hinweise:**
|
|
- **Kein Match → Originalwert wird unverändert weitergegeben** (pipeline-sicher)
|
|
- Capture Groups als `$1`, `$2`, … im `replace` referenzieren
|
|
- Pattern ohne `^`/`$`-Anchors ersetzt nur den gematchten Teilstring, nicht den ganzen Wert
|
|
|
|
---
|
|
|
|
### 8. **regexextract** - Regex-Extraktion
|
|
|
|
Extrahiert eine Capture Group per regulärem Ausdruck und gibt **nur diese** zurück. Nutzt PHP `preg_match`.
|
|
|
|
```json
|
|
{
|
|
"sourceColumn": "Mitteilungen",
|
|
"transformations": [
|
|
{
|
|
"type": "regexextract",
|
|
"pattern": "(\\d{4,} [^;]+)"
|
|
}
|
|
],
|
|
"outputColumn": "location",
|
|
"outputAction": "create"
|
|
}
|
|
```
|
|
|
|
**Beispiel — mit Match:**
|
|
- Input: `Coop Pronto Chur, 7007 Chur`
|
|
- Pattern: `(\d{4,} [^;]+)`
|
|
- Output: `7007 Chur` ← nur Capture Group 1
|
|
|
|
**Beispiel — kein Match:**
|
|
- Input: `Dauerauftrag Miete`
|
|
- Output: `` (leerer String)
|
|
|
|
**Hinweise:**
|
|
- **Kein Match → leerer String** (vorherige Pipeline-Schritte gehen verloren)
|
|
- Nutzt Capture Group 1 wenn vorhanden, sonst komplettes Match
|
|
- **⚠ Nicht pipeline-sicher:** Nur als einzigen oder letzten Schritt verwenden. Wenn bei Kein-Match der bisherige Wert erhalten bleiben soll, `regex` verwenden.
|
|
|
|
---
|
|
|
|
### 9. **dateformat** - Datum-Umformat
|
|
|
|
Konvertiert zwischen Datum-Formaten.
|
|
|
|
```json
|
|
{
|
|
"type": "dateformat",
|
|
"fromFormat": "d.m.Y",
|
|
"toFormat": "Y-m-d"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `10.12.2025`
|
|
- Output: `2025-12-10`
|
|
|
|
**Supported Formate:** Alle PHP DateTime-Formate (d, m, Y, H, i, s, etc.)
|
|
|
|
---
|
|
|
|
### 10. **truncate** - String kürzen
|
|
|
|
Kürzt String auf maximale Länge.
|
|
|
|
```json
|
|
{
|
|
"type": "truncate",
|
|
"maxLength": 100
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input: `Dieser sehr lange Text...` (150 Zeichen)
|
|
- Output: `Dieser sehr lange Text...` (100 Zeichen)
|
|
|
|
---
|
|
|
|
### 11. **constantvalue** - Konstanten-Wert aus Metadaten
|
|
|
|
Nutzt extrahierte Metadaten als konstanten Wert.
|
|
|
|
```json
|
|
{
|
|
"sourceColumn": "_constant_",
|
|
"transformations": [
|
|
{
|
|
"type": "constantvalue",
|
|
"metadataKey": "account_iban"
|
|
}
|
|
],
|
|
"outputColumn": "account_iban",
|
|
"outputAction": "create"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- metadataKey: `account_iban` (aus Extraktion)
|
|
- Wert: `CH9300762011623852957`
|
|
- Jede Zeile erhält diesen Wert in neuer Spalte
|
|
|
|
---
|
|
|
|
### 12. **map** - Spalte kopieren (Standard)
|
|
|
|
Kopiert oder benannt eine Spalte um.
|
|
|
|
```json
|
|
{
|
|
"sourceColumn": "Buchungstext",
|
|
"transformations": [
|
|
{
|
|
"type": "map"
|
|
}
|
|
],
|
|
"outputColumn": "description",
|
|
"outputAction": "overwrite"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
- Input Spalte: `Buchungstext`
|
|
- Output Spalte: `description` mit gleichem Inhalt
|
|
|
|
---
|
|
|
|
### 13. **pipeline** - Verschachtelte Pipeline
|
|
|
|
Führt eine Unter-Pipeline innerhalb eines Transformationsschritts aus. Ermöglicht das Gruppieren von Schritten als Einheit.
|
|
|
|
```json
|
|
{
|
|
"type": "pipeline",
|
|
"steps": [
|
|
{ "type": "trim" },
|
|
{ "type": "lowercase" },
|
|
{ "type": "ucwordsfirst" }
|
|
]
|
|
}
|
|
```
|
|
|
|
**Hinweis:** In der Praxis werden mehrere Schritte direkt als `transformations`-Array aufgelistet. `pipeline` als Typ ist nützlich wenn innerhalb einer `transformations`-Liste eine Gruppe von Schritten bedingt oder als Einheit behandelt werden soll.
|
|
|
|
---
|
|
|
|
### Pipeline-Beispiel
|
|
|
|
Mehrere Transformationen hintereinander:
|
|
|
|
```json
|
|
{
|
|
"sourceColumn": "Buchungstext",
|
|
"transformations": [
|
|
{ "type": "trim" },
|
|
{ "type": "replace", "search": " ", "replace": " " },
|
|
{ "type": "lowercase" },
|
|
{ "type": "ucwordsfirst" }
|
|
],
|
|
"outputColumn": "description",
|
|
"outputAction": "overwrite"
|
|
}
|
|
```
|
|
|
|
**Verarbeitung:**
|
|
1. `" COOP PRONTO "` → trim → `"COOP PRONTO"`
|
|
2. `"COOP PRONTO"` → replace → `"COOP PRONTO"`
|
|
3. `"COOP PRONTO"` → lowercase → `"coop pronto"`
|
|
4. `"coop pronto"` → ucwordsfirst → `"Coop Pronto"`
|
|
|
|
---
|
|
|
|
## CLI-Referenz
|
|
|
|
Der Transformer wird über `bin/transformer.php` aufgerufen:
|
|
|
|
```bash
|
|
php bin/transformer.php <command> <config> <input> [options]
|
|
```
|
|
|
|
### Kommandos
|
|
|
|
#### `process` - Führe Transformation aus
|
|
|
|
```bash
|
|
php bin/transformer.php process config/config.json input.csv [--debug]
|
|
```
|
|
|
|
- Transformiert CSV-Datei komplett
|
|
- Schreibt in `directories.output` (aus config)
|
|
- Optional: `--debug` für Debug-Logs
|
|
|
|
**Output:**
|
|
```
|
|
✓ Transformation erfolgreich
|
|
Input: input.csv
|
|
Output: config/import/output/transformed.csv
|
|
Zeilen: 245
|
|
Sample:
|
|
- [Datum: 2025-01-10, Beschreibung: ...]
|
|
```
|
|
|
|
---
|
|
|
|
#### `validate` - Validiere CSV
|
|
|
|
```bash
|
|
php bin/transformer.php validate config/config.json input.csv
|
|
```
|
|
|
|
- Prüft CSV-Format
|
|
- Extrahiert Metadaten
|
|
- Validiert erforderliche Felder
|
|
|
|
**Output:**
|
|
```
|
|
✓ CSV ist valid
|
|
Zeilen: 245
|
|
IBAN: CH9300762011623852957
|
|
Währung: CHF
|
|
```
|
|
|
|
---
|
|
|
|
#### `test` - Test-Run mit Beispieldaten
|
|
|
|
```bash
|
|
php bin/transformer.php test config/config.json input.csv [--debug]
|
|
```
|
|
|
|
- Transformiert maximal 10 Zeilen
|
|
- Zeigt Metadaten und Beispiel-Output
|
|
- Schnell zur Prüfung von Konfiguration
|
|
|
|
**Output:**
|
|
```
|
|
✓ Test erfolgreich
|
|
Max 10 Zeilen verarbeitet: 10
|
|
Metadaten:
|
|
- IBAN: CH93...
|
|
- Währung: CHF
|
|
Beispiel (Zeile 1):
|
|
- date: 2025-01-10
|
|
- description: coop pronto chur
|
|
- amount: 25.50
|
|
```
|
|
|
|
---
|
|
|
|
#### `help` - Zeige Hilfe
|
|
|
|
```bash
|
|
php bin/transformer.php help
|
|
```
|
|
|
|
---
|
|
|
|
### Optionen
|
|
|
|
| Option | Beschreibung | Beispiel |
|
|
|--------|-------------|---------|
|
|
| `--debug` | Aktiviere Debug-Modus | `process config.json input.csv --debug` |
|
|
| `--test` | Führe nur Test mit 10 Zeilen aus | `process config.json input.csv --test` |
|
|
|
|
---
|
|
|
|
## Debug-Modus
|
|
|
|
Der Debug-Modus bietet maximale Transparenz über die Verarbeitung.
|
|
|
|
### Aktivierung
|
|
|
|
```bash
|
|
php bin/transformer.php process config/config.json input.csv --debug
|
|
```
|
|
|
|
### Ausgegabene Informationen
|
|
|
|
Der Debug-Modus protokolliert:
|
|
|
|
**1. Transformer Level**
|
|
- Transformation gestartet (Input-Datei, maxRows)
|
|
- Transformation abgeschlossen
|
|
- Fehler
|
|
|
|
**2. CSV Reader Level**
|
|
- Metadaten-Zeilen gelesen (Anzahl)
|
|
- Datenzeilen gelesen (Anzahl)
|
|
|
|
**3. Metadata Extraction Level**
|
|
- Extraktion-Regel angewendet
|
|
- IBAN extrahiert
|
|
- Währung extrahiert
|
|
- Fehlerhafte Regex
|
|
- Fehlende Zeilen
|
|
|
|
**4. Transformation Level**
|
|
- Split-Transformation angewendet
|
|
- RegexExtract-Transformation angewendet
|
|
- Fehlerhafte Transformationen
|
|
|
|
**5. CSV Writer Level**
|
|
- Transformierte Daten geschrieben
|
|
- Output-Datei-Pfad
|
|
|
|
### JSON-Output mit Debug-Logs
|
|
|
|
Mit `--debug` wird das Ergebnis erweitert:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"inputFile": "input.csv",
|
|
"outputFile": "output/transformed.csv",
|
|
"rowsProcessed": 245,
|
|
"metadata": { "account_iban": "CH93...", "currency_code": "CHF" },
|
|
"debug_logs": [
|
|
{
|
|
"timestamp": 1702200120.5432,
|
|
"category": "transformer",
|
|
"message": "Transformation started",
|
|
"data": { "inputFile": "input.csv", "maxRows": 0 }
|
|
},
|
|
{
|
|
"timestamp": 1702200120.5445,
|
|
"category": "metadata",
|
|
"message": "Extraction rule applied",
|
|
"data": { "rule_name": "account_iban", "value": "CH93..." }
|
|
}
|
|
// ... weitere Logs
|
|
]
|
|
}
|
|
```
|
|
|
|
### Debug-Log-Kategorien
|
|
|
|
| Kategorie | Beispiel | Wann |
|
|
|-----------|---------|------|
|
|
| `transformer` | Transformation gestartet | Anfang/Ende Transformation |
|
|
| `csv_reader` | Zeilen gelesen | Beim CSV lesen |
|
|
| `metadata` | IBAN extrahiert | Bei Metadaten-Extraktion |
|
|
| `metadata_warning` | Regex matched nicht | Bei Problemen |
|
|
| `transformation` | Split angewendet | Bei jeder Transformation |
|
|
| `csv_writer` | Daten geschrieben | Beim CSV schreiben |
|
|
|
|
---
|
|
|
|
## Firefly III Integration
|
|
|
|
Der Transformer kann transformierte Daten automatisch in Firefly III importieren.
|
|
|
|
### Setup
|
|
|
|
1. **Firefly III laufen lassen**
|
|
|
|
```bash
|
|
docker-compose up -d firefly-iii
|
|
docker-compose up -d firefly-importer
|
|
```
|
|
|
|
2. **Konfiguration anpassen**
|
|
|
|
```json
|
|
{
|
|
"fireflyImport": {
|
|
"autoImport": true,
|
|
"environment": {
|
|
"FIREFLY_III_URL": "https://your-firefly.local",
|
|
"FIREFLY_III_ACCESS_TOKEN": "your-personal-access-token"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
3. **Import-Konfiguration erstellen**
|
|
|
|
`/opt/firefly/import-config.json`:
|
|
```json
|
|
{
|
|
"accounts": [
|
|
{
|
|
"name": "UBS Checking",
|
|
"iban": "CH9300762011623852957",
|
|
"account_type": "asset"
|
|
}
|
|
],
|
|
"column_mapping": {
|
|
"date": "date",
|
|
"amount": "amount",
|
|
"description": "description"
|
|
}
|
|
}
|
|
```
|
|
|
|
4. **Auto-Import aktivieren**
|
|
|
|
```bash
|
|
php bin/transformer.php process config/config.json input.csv
|
|
# Wenn autoImport=true, wird die transformierte Datei automatisch importiert
|
|
```
|
|
|
|
### Manueller Import
|
|
|
|
```bash
|
|
docker exec -it firefly-importer php artisan importer:import
|
|
```
|
|
|
|
---
|
|
|
|
## Architektur
|
|
|
|
### Komponenten
|
|
|
|
```
|
|
bin/transformer.php (CLI Entry Point)
|
|
↓
|
|
TransformerEngine (Orchestrierung)
|
|
├─ ConfigurationLoader (Config laden/validieren)
|
|
├─ CsvReader (CSV einlesen)
|
|
├─ MetadataExtractor (Metadaten mit Regex)
|
|
├─ ColumnTransformer (Transformationen anwenden)
|
|
├─ CsvWriter (CSV schreiben)
|
|
├─ FireflyImporter (Firefly III Integration)
|
|
└─ DebugLogger (Debug-Protokolle)
|
|
```
|
|
|
|
### Datenfluss
|
|
|
|
```
|
|
Input CSV
|
|
↓
|
|
CsvReader::readMetadataLines() → Array von Zeilen
|
|
↓
|
|
MetadataExtractor::extract() → {iban: "...", currency: "..."}
|
|
↓
|
|
CsvReader::readCsvData() → Array von Zeilen
|
|
↓
|
|
ColumnTransformer::transformRow() → Transformierte Zeile (Pipeline)
|
|
↓
|
|
CsvWriter::write() → Output CSV
|
|
```
|
|
|
|
### Klassen
|
|
|
|
| Klasse | Verantwortung |
|
|
|--------|---------------|
|
|
| `TransformerEngine` | Orchestriert gesamten Workflow |
|
|
| `ConfigurationLoader` | Lädt JSON/YAML Konfiguration |
|
|
| `CsvReader` | Liest CSV mit Metadaten |
|
|
| `MetadataExtractor` | Extrahiert mit Regex |
|
|
| `ColumnTransformer` | Transformiert Spalten (Pipeline) |
|
|
| `CsvWriter` | Schreibt CSV |
|
|
| `FireflyImporter` | Importiert in Firefly III |
|
|
| `DebugLogger` | Statischer Logger für Debug |
|
|
|
|
---
|
|
|
|
## Fehlerbehandlung
|
|
|
|
### Häufige Fehler
|
|
|
|
#### 1. "Input-Datei nicht gefunden"
|
|
|
|
```bash
|
|
Error: Input-Datei nicht gefunden: input.csv
|
|
```
|
|
|
|
**Ursache:** Dateipfad falsch oder Datei nicht vorhanden
|
|
|
|
**Lösung:**
|
|
```bash
|
|
# Prüfe Dateipfad
|
|
ls -la input.csv
|
|
|
|
# Nutze absoluten Pfad wenn relativ nicht funktioniert
|
|
php bin/transformer.php process config.json /absolute/path/input.csv
|
|
```
|
|
|
|
---
|
|
|
|
#### 2. "Fehlende Metadaten: account_iban"
|
|
|
|
```bash
|
|
Error: Fehlende Metadaten: account_iban
|
|
```
|
|
|
|
**Ursache:** IBAN konnte nicht extrahiert werden (Regex oder Zeile falsch)
|
|
|
|
**Lösung:**
|
|
```bash
|
|
# Debugging mit --debug
|
|
php bin/transformer.php validate config.json input.csv
|
|
|
|
# Prüfe erste 5 Zeilen des CSV
|
|
head -5 input.csv
|
|
|
|
# Überprüfe lineNumber und regex in config.json
|
|
# lineNumber sollte auf Zeile mit IBAN zeigen
|
|
```
|
|
|
|
---
|
|
|
|
#### 3. "Ungültiges JSON"
|
|
|
|
```bash
|
|
Error: Ungültiges JSON: Syntax error, malformed JSON
|
|
```
|
|
|
|
**Ursache:** JSON-Syntax-Fehler in config.json
|
|
|
|
**Lösung:**
|
|
```bash
|
|
# Validiere JSON
|
|
php -r "json_decode(file_get_contents('config/config.json'), true) or die('JSON invalid');"
|
|
|
|
# Oder nutze online JSON validator
|
|
# https://jsonlint.com/
|
|
```
|
|
|
|
---
|
|
|
|
#### 4. "CSV-Struktur-Fehler"
|
|
|
|
```bash
|
|
Error: 'csvStructure.headerLine' erforderlich
|
|
```
|
|
|
|
**Ursache:** Erforderliche Konfigurationsfelder fehlen
|
|
|
|
**Lösung:**
|
|
```bash
|
|
# Vergleiche mit config.example.json
|
|
diff config/config.json config/config.example.json
|
|
|
|
# Stellen Sie sicher, dass folgende Felder vorhanden sind:
|
|
# - csvStructure.headerLine (Zeilennummer der Kopfzeile)
|
|
# - csvStructure.delimiter (CSV-Trennzeichen)
|
|
# - metadata.extractionRules (mindestens 1)
|
|
# - columnTransformations (mindestens 1)
|
|
```
|
|
|
|
---
|
|
|
|
### Exception-Handling
|
|
|
|
Der Transformer nutzt Try-Catch für robuste Fehlerbehandlung:
|
|
|
|
```php
|
|
try {
|
|
$result = $engine->transform($inputFile);
|
|
if (!$result['success']) {
|
|
echo "Fehler: " . $result['error'];
|
|
}
|
|
} catch (Exception $e) {
|
|
echo "Fatal Error: " . $e->getMessage();
|
|
}
|
|
```
|
|
|
|
### Debug-Modus für Fehlersuche
|
|
|
|
Der Debug-Modus zeigt detailliert wo der Fehler liegt:
|
|
|
|
```bash
|
|
php bin/transformer.php process config/config.json input.csv --debug 2>&1 | tail -50
|
|
```
|
|
|
|
---
|
|
|
|
## Besonderheiten & Tipps
|
|
|
|
### UTF-8 Handling
|
|
|
|
Der Transformer nutzt UTF-8 safe Funktionen:
|
|
- `mb_strtolower()` statt `strtolower()`
|
|
- `mb_strtoupper()` statt `strtoupper()`
|
|
- `mb_strlen()` für korrektes Character-Counting
|
|
|
|
Unterstützte Encodings: UTF-8, ISO-8859-1, CP1252
|
|
|
|
### Regex-Tipps
|
|
|
|
**Pattern ohne Delimiter:**
|
|
```json
|
|
"pattern": "IBAN:\\s*([A-Z0-9 ]+)"
|
|
// Wird zu: /IBAN:\s*([A-Z0-9 ]+)/u
|
|
```
|
|
|
|
**Mit Flags:**
|
|
```json
|
|
"pattern": "/IBAN:\\s*([A-Z0-9 ]+)/iu"
|
|
// Case-insensitive
|
|
```
|
|
|
|
**Spezielle Zeichen escapen:**
|
|
```json
|
|
"pattern": "\\(\\d{4}\\)"
|
|
// Matcht: (1234)
|
|
```
|
|
|
|
### Performance
|
|
|
|
- **Max. Dateigröße:** Abhängig von RAM (typically 100MB+)
|
|
- **Optimiert für:** Bis zu 1 Million Zeilen
|
|
- **Typical:** 10-100k Zeilen pro Datei
|
|
|
|
### Batch-Processing
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
for file in import/source/*.csv; do
|
|
php bin/transformer.php process config/config.json "$file"
|
|
if [ $? -eq 0 ]; then
|
|
mv "$file" import/archive/
|
|
else
|
|
mv "$file" import/error/
|
|
fi
|
|
done
|
|
```
|
|
|
|
---
|
|
|
|
## Support & Troubleshooting
|
|
|
|
### Logging aktivieren
|
|
|
|
Nutze den Built-in Debug-Logger:
|
|
|
|
```bash
|
|
php bin/transformer.php test config/config.json input.csv --debug > debug.log 2>&1
|
|
cat debug.log | grep -i error
|
|
```
|
|
|
|
### Nützliche Kommandos
|
|
|
|
```bash
|
|
# Test CSV-Validität
|
|
php bin/transformer.php validate config.json input.csv
|
|
|
|
# Test nur mit 10 Zeilen
|
|
php bin/transformer.php test config.json input.csv
|
|
|
|
# Mit voller Debug-Ausgabe
|
|
php bin/transformer.php process config.json input.csv --debug
|
|
|
|
# Prüfe PHP-Syntax aller Dateien
|
|
php -l bin/transformer.php
|
|
php -l src/*.php
|
|
|
|
# Validiere Konfiguration
|
|
php -r "require 'src/ConfigurationLoader.php'; new UbsCsvTransformer\ConfigurationLoader('config/config.json');"
|
|
```
|
|
|
|
---
|
|
|
|
## Version & Änderungen
|
|
|
|
**v1.0.0 (10. Dezember 2025)**
|
|
- ✅ Initial Release
|
|
- ✅ 11 Transformationstypen
|
|
- ✅ Metadaten-Extraktion mit Regex
|
|
- ✅ Debug-Modus
|
|
- ✅ Firefly III Integration
|
|
- ✅ Vollständige Dokumentation
|
|
|
|
---
|
|
|
|
**Lizenz:** MIT
|
|
**Author:** PHP CSV Transformer Project
|
|
**Repository:** https://git.andare.ch/david.reindl/ff-imp-preprocessor |