docs: Factory-Defaults Import/Export-Anleitung in READMEs

Haupt-README.md: neuer Abschnitt mit Abgrenzung zu Datenbank-Backup, Schritt-
für-Schritt-Anleitung für Export und Import, Idempotenz-Hinweis, Berechtigungen.

backend/factory-defaults/README.md: ausführliche Referenz mit Struktur-Beispielen
aller JSON-Dateien (Provider, CancellationPeriod, ContractDuration,
ContractCategory, PdfTemplate), Teil-Import-Anleitung, Merge-Beispiele.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck 2026-04-23 14:19:02 +02:00
parent 60dc98e265
commit 109f774d62
2 changed files with 358 additions and 30 deletions

117
README.md
View File

@ -916,6 +916,123 @@ Folgende Felder werden in Audit-Logs gefiltert:
- API-Response wird nicht blockiert
- Before/After-Werte über Prisma Middleware
## Factory-Defaults: Stammdaten-Kataloge teilen
Das **Factory-Defaults**-System erlaubt den Export und Import von
Stammdaten-Katalogen (Anbieter, Tarife, PDF-Vorlagen usw.) zwischen verschiedenen
OpenCRM-Installationen. Es ist bewusst **streng abgegrenzt** zu Datenbank-Backups:
### Abgrenzung
| | Factory-Defaults | Datenbank-Backup |
|---|---|---|
| Anbieter, Tarife, Kündigungsfristen, Laufzeiten, Kategorien | ✅ | ✅ |
| PDF-Auftragsvorlagen (inkl. Dateien + Feldzuordnungen) | ✅ | ✅ |
| **Kundendaten, Verträge, Dokumente** | ❌ | ✅ |
| **Emails, SMTP-/IMAP-Zugangsdaten** | ❌ | ✅ |
| **System-Einstellungen, Datenschutzerklärungen, Impressum** | ❌ | ✅ |
| Zwischen verschiedenen Installationen teilbar | ✅ | ❌ (zu firmen-spezifisch) |
> **Kurz:** Factory-Defaults = reine Kataloge, Backup = alles.
### Export (Installation A → ZIP)
1. **Einstellungen****Factory-Defaults** öffnen
2. Übersicht prüfen (Anzahl pro Kategorie)
3. Button **„Factory-Defaults exportieren"** klicken
4. ZIP wird als `factory-defaults-YYYY-MM-DD.zip` heruntergeladen
**ZIP-Struktur:**
```
factory-defaults-2026-04-23.zip
├── manifest.json # Version + Datum + Counts
├── providers/
│ └── providers.json # Anbieter inkl. zugehöriger Tarife
├── contract-meta/
│ ├── cancellation-periods.json # Kündigungsfristen (Code + Beschreibung)
│ ├── contract-durations.json # Laufzeiten (Code + Beschreibung)
│ └── contract-categories.json # Kategorien (Strom, Gas, DSL, ...)
└── pdf-templates/
├── pdf-templates.json # Vorlagen-Metadaten + Feldzuordnungen
└── *.pdf # Die eigentlichen PDF-Dateien
```
Die ZIP kann an andere Installationen weitergegeben werden
(Partner, Test-System, neue Installation).
### Import (ZIP → Installation B)
1. ZIP herunterladen bzw. erhalten
2. Inhalt nach `backend/factory-defaults/` entpacken (Unterordnerstruktur beibehalten)
3. Im Backend-Verzeichnis ausführen:
```bash
npm run seed:defaults
```
**Beispiel-Output:**
```
📦 Factory-Defaults werden eingespielt...
✓ Anbieter: 7, Tarife: 12
✓ Kündigungsfristen: 5
✓ Laufzeiten: 4
✓ Vertragskategorien: 8
✓ PDF-Vorlagen: 3
✅ Factory-Defaults erfolgreich eingespielt.
```
### Mehrere ZIPs kombinieren
Du kannst mehrere Exporte in `backend/factory-defaults/` übereinanderlegen
JSON-Dateien werden automatisch gemerged:
```
backend/factory-defaults/
providers/
verivox.json # 40 Anbieter aus Verivox-Paket
check24.json # 30 Anbieter aus Check24-Paket
eigene.json # 5 eigene Anbieter
```
Das Import-Script liest **alle** `*.json` im jeweiligen Unterordner und merged per
unique Key (letzter Eintrag gewinnt). Duplikate sind also unproblematisch.
### Idempotenz
Das Script nutzt ausschließlich Prisma `upsert`:
- **Neue Einträge** werden angelegt
- **Bestehende Einträge** (per unique Key: `name`, `code`) werden aktualisiert
- Nichts wird gelöscht
Du kannst `npm run seed:defaults` also beliebig oft ausführen, ohne Datenverlust
oder Duplikate.
### PDF-Dateien beim Import
Beim Import werden PDF-Vorlagen aus `factory-defaults/pdf-templates/*.pdf` nach
`uploads/pdf-templates/` kopiert und die Pfade in der DB entsprechend gesetzt.
Beim Re-Import wird die alte Datei in `uploads/` entsorgt und durch die neue
ersetzt.
### Berechtigungen
| Aktion | Berechtigung |
|--------|--------------|
| Factory-Defaults Vorschau | `settings:read` |
| Factory-Defaults Export | `settings:update` |
| Factory-Defaults Import (CLI) | Server-Zugang (SSH/Shell) |
### Typischer Einsatzzweck
- **Neue Installation aufsetzen**: Eine Kollegen-ZIP importieren und sofort mit
gepflegtem Anbieter- und Vorlagenkatalog loslegen
- **Vorlagen-Paket teilen**: Eine ZIP mit nur PDF-Vorlagen weitergeben
(die anderen Ordner einfach aus der ZIP entfernen vor dem Entpacken)
- **Anbieter-Paket teilen**: ZIP mit nur `providers/` weitergeben
- **Versionskontrolle**: Die entpackten JSON-Dateien unter Versionskontrolle
stellen (außerhalb von `backend/factory-defaults/`, da der Ordner gitignored ist)
## Lizenz
MIT

View File

@ -3,43 +3,254 @@
Dieser Ordner enthält **Stammdaten-Kataloge**, die beim Initialisieren einer neuen
OpenCRM-Installation automatisch eingespielt werden können.
## Was ist drin?
Siehe auch den Abschnitt „Factory-Defaults" in der Haupt-[README.md](../../README.md)
für einen Gesamtüberblick und die Abgrenzung zum Datenbank-Backup.
- `providers.json` Anbieter inkl. zugehöriger Tarife
- `cancellation-periods.json` Kündigungsfristen (z.B. "14 Tage", "1 Monat")
- `contract-durations.json` Vertragslaufzeiten (z.B. "12 Monate", "24 Monate")
- `contract-categories.json` Vertragskategorien (Strom, Gas, DSL …)
- `pdf-templates.json` + `pdf-templates/*.pdf` PDF-Auftragsvorlagen mit Feldzuordnungen
---
**NICHT enthalten sind Kundendaten, Verträge, Dokumente, E-Mails oder SMTP-Einstellungen.**
Dafür gibt es den separaten Datenbank-Backup-Export.
## Inhalt
## Wie nutze ich das?
### Export (aus bestehender Installation)
In den CRM-Einstellungen → Factory-Defaults → „Exportieren" → ZIP herunterladen
und den Inhalt in diesen Ordner entpacken.
### Import
```bash
npm run seed:defaults
```
backend/factory-defaults/
├── providers/
│ └── providers.json # Anbieter inkl. Tarife
├── contract-meta/
│ ├── cancellation-periods.json # Kündigungsfristen
│ ├── contract-durations.json # Vertragslaufzeiten
│ └── contract-categories.json # Vertragskategorien (Strom/Gas/DSL/...)
└── pdf-templates/
├── pdf-templates.json # Metadaten + Feldzuordnungen
└── *.pdf # PDF-Vorlagen-Dateien
```
Das Script liest alle Dateien aus diesem Ordner, merged mehrere JSONs automatisch
per unique-name und spielt sie per Prisma `upsert` ein. Kann mehrfach ausgeführt
werden (idempotent).
**Was NICHT enthalten ist:** Kundendaten, Verträge, Dokumente, E-Mails, SMTP-Einstellungen,
Datenschutzerklärungen oder andere AppSettings. Dafür gibt es den separaten
**Datenbank-Backup-Export** (Einstellungen → Datenbank & Zurücksetzen).
## Mehrere Export-Dateien mergen
---
Wenn du mehrere ZIPs entpackst (z.B. Provider-Pakete von verschiedenen Quellen),
kannst du die JSON-Dateien frei umbenennen das Script liest alle `*.json` im
jeweiligen Unterordner und merged den Inhalt zusammen.
## Export (aus einer bestehenden Installation)
1. Im CRM als Admin einloggen
2. **Einstellungen** → **Factory-Defaults**
3. Auf **„Factory-Defaults exportieren"** klicken
4. Die heruntergeladene ZIP (`factory-defaults-YYYY-MM-DD.zip`) speichern
### Inhalt der ZIP
Beispiel:
```
providers/
verivox.json
check24.json
eigene.json
factory-defaults-2026-04-23.zip
├── manifest.json # Version, Datum, Einträge pro Kategorie
├── providers/providers.json
├── contract-meta/cancellation-periods.json
├── contract-meta/contract-durations.json
├── contract-meta/contract-categories.json
├── pdf-templates/pdf-templates.json
└── pdf-templates/*.pdf
```
Alle drei werden eingespielt, gleiche Anbieter werden über den `name` gemerged.
Die ZIP kann an andere Installationen weitergegeben werden z.B. für Test-Systeme,
neue Installationen oder Partner-Setups.
---
## Import (in eine andere Installation)
### Schritt-für-Schritt
1. **ZIP herunterladen** (aus einer Export-Installation oder von einer Vorlage)
2. **Inhalt entpacken** in diesen Ordner (`backend/factory-defaults/`),
Unterordnerstruktur beibehalten
3. **Script ausführen:**
```bash
cd backend
npm run seed:defaults
```
4. **Ausgabe prüfen** bei Erfolg:
```
📦 Factory-Defaults werden eingespielt...
✓ Anbieter: 7, Tarife: 12
✓ Kündigungsfristen: 5
✓ Laufzeiten: 4
✓ Vertragskategorien: 8
✓ PDF-Vorlagen: 3
✅ Factory-Defaults erfolgreich eingespielt.
```
### Idempotenz
Das Script nutzt ausschließlich `upsert`:
- **Neue Einträge** werden angelegt
- **Bestehende Einträge** (match per unique key: `name` / `code`) werden aktualisiert
- Nichts wird gelöscht
Du kannst `npm run seed:defaults` **beliebig oft ausführen** kein Datenverlust,
keine Duplikate.
### Was passiert mit den PDF-Dateien?
Die PDFs aus `pdf-templates/*.pdf` werden beim Import nach
`backend/uploads/pdf-templates/` kopiert (mit eindeutigem Zeitstempel-Suffix).
Die Pfade in der DB werden automatisch auf die neue Kopie gesetzt.
Beim Re-Import einer bereits existierenden Vorlage wird die alte Datei in `uploads/`
entsorgt und durch die neue ersetzt.
---
## Mehrere Exporte mergen
Wenn du mehrere ZIPs hast (z.B. "Verivox-Paket", "Check24-Paket", "eigene"), kannst
du die JSON-Dateien frei benennen und in einen Ordner legen. Das Script liest
alle `*.json` im jeweiligen Unterordner und merged den Inhalt zusammen.
**Beispiel:**
```
backend/factory-defaults/
providers/
verivox.json # 40 Anbieter aus dem Verivox-Paket
check24.json # 30 Anbieter aus dem Check24-Paket
eigene.json # 5 eigene, firmenspezifische Anbieter
contract-meta/
standard.json # Standard-Kündigungsfristen + Laufzeiten + Kategorien
pdf-templates/
ewe-paket.json # EWE-Vorlage
moon-paket.json # Moon-Vorlage
ewe-auftrag.pdf
moon-formular.pdf
```
Bei gleichem Unique-Key (z.B. `providers.name: "EWE"` in mehreren Dateien) gewinnt
der zuletzt gelesene Eintrag.
---
## Teil-Import (nur Kategorien auswählen)
Falls du nur einen Teil importieren willst (z.B. nur PDF-Vorlagen ohne Anbieter),
lösche oder verschiebe einfach die nicht gewünschten JSON-Dateien, bevor du das
Script ausführst. Das Script überspringt Kategorien ohne Dateien ohne Fehler.
**Beispiel: nur PDF-Vorlagen:**
```
backend/factory-defaults/
pdf-templates/ # nur diesen Ordner behalten
pdf-templates.json
*.pdf
```
---
## Struktur-Referenz (für manuelle Pflege)
### `providers/providers.json`
Array von Providern, jeweils inkl. zugehöriger Tarife:
```json
[
{
"name": "EWE",
"portalUrl": "https://www.ewe.de/privatkunden/meine-ewe/login",
"usernameFieldName": "username",
"passwordFieldName": "password",
"isActive": true,
"tariffs": [
{ "name": "EWE Zuhause Strom", "isActive": true },
{ "name": "EWE Zuhause Gas", "isActive": true }
]
}
]
```
**Unique Key:** `name`
### `contract-meta/cancellation-periods.json`
```json
[
{ "code": "14T", "description": "14 Tage", "isActive": true },
{ "code": "1M", "description": "1 Monat", "isActive": true },
{ "code": "3M", "description": "3 Monate", "isActive": true }
]
```
**Unique Key:** `code`
### `contract-meta/contract-durations.json`
```json
[
{ "code": "12M", "description": "12 Monate", "isActive": true },
{ "code": "24M", "description": "24 Monate", "isActive": true }
]
```
**Unique Key:** `code`
### `contract-meta/contract-categories.json`
```json
[
{
"code": "ELECTRICITY",
"name": "Strom",
"icon": "Zap",
"color": "#FFC107",
"sortOrder": 1,
"isActive": true
}
]
```
**Unique Key:** `code`
### `pdf-templates/pdf-templates.json`
```json
[
{
"name": "EWE Auftragsformular",
"description": "Auftrag für Glasfaser-Anschluss",
"providerName": "EWE",
"originalName": "EWE-Auftrag-Privat.pdf",
"fieldMapping": {
"Vorname": "customer.firstName",
"Nachname": "customer.lastName",
"Strasse": "address.streetFull",
"PLZ": "address.postalCode",
"Ort": "address.city"
},
"phoneFieldPrefix": "Rufnummer",
"maxPhoneFields": 8,
"isActive": true,
"pdfFilename": "EWE_Auftragsformular.pdf"
}
]
```
**Unique Key:** `name`
**Wichtig:** Die `pdfFilename` muss zu einer PDF-Datei im selben Ordner passen.
---
## Berechtigungen
| Aktion | Berechtigung |
|--------|--------------|
| Factory-Defaults Vorschau | `settings:read` |
| Factory-Defaults Export (UI) | `settings:update` |
| Factory-Defaults Import (CLI) | Server-Zugang (SSH/Shell) |
---
## Git & Versionierung
Dieser Ordner ist in `.gitignore` eingetragen (außer `.gitkeep` und `README.md`),
damit firmen-spezifische Exporte nicht versehentlich ins Repo kommen.
Wenn du **öffentlich teilbare Katalog-Pakete** versionieren willst, lege sie
außerhalb dieses Ordners ab (z.B. in einem eigenen Repository) und kopiere sie
bei Bedarf hierher.