# Factory Defaults Dieser Ordner enthält **Stammdaten-Kataloge**, die beim Initialisieren einer neuen OpenCRM-Installation automatisch eingespielt werden können. Siehe auch den Abschnitt „Factory-Defaults" in der Haupt-[README.md](../../README.md) für einen Gesamtüberblick und die Abgrenzung zum Datenbank-Backup. --- ## Inhalt ``` 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 ``` **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). --- ## 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 ``` 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 ``` 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.