# 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
└── app-settings/
    └── app-settings.json           # HTML-Templates: Datenschutz / Impressum /
                                    # Vollmacht / Website-Datenschutz
```

**Was NICHT enthalten ist:** Kundendaten, Verträge, Dokumente, E-Mails, SMTP-Einstellungen,
Secrets oder benutzerspezifische AppSettings. Dafür gibt es den separaten
**Datenbank-Backup-Export** (Einstellungen → Datenbank & Zurücksetzen).

Bei den AppSettings ist nur eine **Whitelist** vorgesehen (HTML-Texte für rechtliche
Standardpflichten) – andere Keys werden beim Import ignoriert.

---

## 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
└── app-settings/app-settings.json
```

Die ZIP kann an andere Installationen weitergegeben werden – z.B. für Test-Systeme,
neue Installationen oder Partner-Setups.

---

## Import (in eine andere Installation)

### Variante A: Über die UI (empfohlen)

1. Im Ziel-CRM als Admin einloggen
2. **Einstellungen → Factory-Defaults**
3. Im Bereich **Import** auf **„ZIP hochladen"** klicken
4. Die exportierte ZIP wählen – der Import läuft direkt
5. Erfolgsmeldung zeigt Counts pro Kategorie an

### Variante B: Über die CLI (für Bare-Metal / Migration / mehrere ZIPs zusammenführen)

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.

### `app-settings/app-settings.json`

HTML-Standardtexte als Werkseinstellung. Es ist eine **Whitelist** aktiv – andere Keys
werden beim Import ignoriert (Schutz vor versehentlichem Überschreiben von Secrets).

```json
[
  { "key": "privacyPolicyHtml",        "value": "<h1>Datenschutzerklärung</h1>..." },
  { "key": "imprintHtml",              "value": "<h1>Impressum</h1>..." },
  { "key": "authorizationTemplateHtml","value": "<h1>Vollmacht</h1>..." },
  { "key": "websitePrivacyPolicyHtml", "value": "<h1>Website-Datenschutz</h1>..." }
]
```

**Unique Key:** `key`
**Erlaubte Keys:** `privacyPolicyHtml`, `imprintHtml`, `authorizationTemplateHtml`,
`websitePrivacyPolicyHtml`.

---

## Berechtigungen

| Aktion | Berechtigung |
|--------|--------------|
| Factory-Defaults Vorschau | `settings:read` |
| Factory-Defaults Export (UI) | `settings:update` |
| Factory-Defaults Import (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.
