Factory-Defaults: Export + Import von Stammdaten-Katalogen

Ein neues System um Stammdaten-Kataloge zwischen Installationen zu teilen –
explizit ohne Kundendaten, Verträge oder Einstellungen.

**Was wird exportiert:**
- Anbieter + zugehörige Tarife
- Kündigungsfristen
- Vertragslaufzeiten
- Vertragskategorien
- PDF-Auftragsvorlagen (JSON + PDF-Dateien + Feldzuordnungen)

**Was NICHT:**
- Kundendaten, Verträge, Dokumente, Emails, SMTP-Einstellungen
  → dafür gibt es den Datenbank-Backup

**Neue Einstellungsseite /settings/factory-defaults:**
- Zeigt Anzahl pro Kategorie (Anbieter, Tarife, Fristen, …)
- "Exportieren"-Button lädt ZIP herunter (manifest.json + JSONs + PDFs)
- Import-Anleitung inline

**Import-Script:**
- `npm run seed:defaults` (tsx scripts/seed-factory-defaults.ts)
- Liest alle JSON-Dateien aus backend/factory-defaults/*/*.json
- Merged mehrere Dateien automatisch pro Kategorie (unique-key gewinnt zuletzt)
- Upsertet idempotent → kann mehrfach ausgeführt werden
- Kopiert PDF-Vorlagen aus factory-defaults/pdf-templates/ nach uploads/pdf-templates/
- Alte PDF-Dateien werden beim Re-Import entsorgt

Backend:
- services/factoryDefaults.service.ts: collectFactoryDefaults() + exportFactoryDefaults()
- controllers/factoryDefaults.controller.ts: preview + export
- routes/factoryDefaults.routes.ts: GET /api/factory-defaults/preview + /export
- scripts/seed-factory-defaults.ts: CLI-Import-Script
- .gitignore: factory-defaults/* außer .gitkeep und README.md

Frontend:
- pages/settings/FactoryDefaults.tsx: Übersicht + Export-Button
- Settings-Karte „Factory-Defaults" im System-Abschnitt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 14:10:12 +02:00
parent 9d5412cef0
commit ad49b92ee9
13 changed files with 913 additions and 40 deletions
+18 -1
View File
@@ -1,7 +1,7 @@
import { Link } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import Card from '../components/ui/Card';
import { Settings as SettingsIcon, Code, Store, Clock, Calendar, UserCog, ChevronRight, Building2, FileType, Eye, Globe, Mail, Database, Shield, FileText, FileEdit } from 'lucide-react';
import { Settings as SettingsIcon, Code, Store, Clock, Calendar, UserCog, ChevronRight, Building2, FileType, Eye, Globe, Mail, Database, Shield, FileText, FileEdit, PackageCheck } from 'lucide-react';
export default function Settings() {
const { hasPermission, developerMode, setDeveloperMode } = useAuth();
@@ -177,6 +177,23 @@ export default function Settings() {
</div>
</div>
</Link>
<Link
to="/settings/factory-defaults"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<PackageCheck className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Factory-Defaults
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Stammdaten-Kataloge (Anbieter, Tarife, PDF-Vorlagen) exportieren ohne Kundendaten.</p>
</div>
</div>
</Link>
{hasPermission('audit:read') && (
<Link
to="/settings/audit-logs"