# Importe Letzte Aktualisierung: 2026-02-22 Diese Seite beschreibt den V1 CSV-Import unter `/admin/imports`. ## Technischer Aufbau - Das Import-Modul ist instanzbasiert über `lib/Service/Import/ImportServicesFactory.php` verdrahtet. - `ImportService` orchestriert Analyze/Preview/Commit. - `ImportStateStoreService` kapselt den tokenbasierten Session-State (`admin_imports_v1`, TTL 2h). - `CsvReaderService` und `ImportTempFileService` sind eigene Instanzservices. - Import-Audit läuft über `ImportAuditService` + `ImportAuditRunRepository`. ## Scope (V1) - Profile: `users`, `departments`. - Create-only: bestehende Einträge werden übersprungen. - CSV mit `,` oder `;`, UTF-8 (BOM wird toleriert). - Limits: 10MB und 20.000 Datenzeilen. - Fehlerausgabe nur in der UI (kein Download in V1). ## Permissions - `imports.view`: Zugriff auf die Import-Seite. - `imports.audit.view`: Zugriff auf Import-Protokolle unter `/admin/import-audit`. - `users.import`: User-Import ausführen. - `users.import_assignments`: Tenant/Role/Department aus CSV verwenden. - `departments.import`: Department-Import ausführen. ## Ablauf 1. Upload - Entität wählen (`Users` oder `Departments`) und CSV hochladen. - Header/Delimiter/Zeilenlimit werden direkt geprüft. 2. Mapping - CSV-Header auf Zielfelder mappen. - Pflichtziele sind profilabhängig. 3. Preview (Dry run) - Keine DB-Schreibvorgänge. - Summary + erste Fehler (maximal 500 Einträge). 4. Commit - Zeilenweise Verarbeitung (`best effort`). - Gültige Zeilen werden erstellt, fehlerhafte reportet. ## Assignment-Regeln - Users: optional `tenant`, `role`, `department` (jeweils 1:1). - Departments: optional `tenant`. - Identifier-Auflösung: - Users: UUID zuerst, ID als Fallback. - Departments: `tenant` ist UUID-only (kein ID-Fallback). - Nur aktive Datensätze sind gültig. - Department muss zum Tenant passen. - Fehlen Assignment-Werte, greifen Defaults aus Settings. - Ohne `users.import_assignments` wird ein Mapping mit Assignment-Spalten sofort abgelehnt. ## Duplikate und Skip-Verhalten - In-File-Duplikate: erste Zeile gewinnt, spätere `duplicate_in_file`. - Users: - bestehende E-Mail: `email_exists` - Departments: - bestehender Code: `code_exists` - bestehende Kombination aus Tenant + Description: `department_exists` ## Temporäre Dateien - Uploads liegen unter `APP_STORAGE_PATH/imports/tmp`. - Dateinamen werden randomisiert. - Cleanup entfernt alte Temp-Dateien opportunistisch (älter als 24h). ## Import-Audit (V1) - Pro Commit-Lauf wird ein Audit-Run gespeichert (`import_audit_runs`). - Analyze/Preview werden bewusst nicht protokolliert. - Gespeichert werden nur Metadaten: - Profil (`users`/`departments`), Status (`success`/`partial`/`failed`) - Laufzeit, Counter (`rows_total`, `created`, `skipped`, `failed`) - User, aktueller Tenant, Dateiname (basename), gemappte Felder - aggregierte Fehlercodes (kein Zeileninhalt) - Keine CSV-Zeilenpayload oder PII-Details im Audit. - Retention: 90 Tage, bereinigbar über `/admin/import-audit` (Purge-Action mit `settings.update`). ## Fehlercodes (V1) - Struktur: `upload_missing`, `upload_too_large`, `invalid_file_type`, `invalid_csv_header`, `empty_csv`, `max_rows_exceeded`, `mapping_required_missing`, `assignment_permission_required` - Zeilenvalidierung: `invalid_email`, `invalid_tenant_uuid`, `duplicate_in_file`, `email_exists`, `code_exists`, `department_exists`, `invalid_locale`, `invalid_active`, `invalid_hire_date`, `tenant_not_found`, `role_not_found`, `department_not_found`, `department_tenant_mismatch`, `assignment_out_of_scope`, `create_failed`, `unexpected_error`