# Entwicklungsplan: Agentur-Attribution → User-Profil (Umbau) > Erstellt **07.07.2026** nach User-Entscheidung. Ziel: Der Firmen-Typ „Agentur" > verschwindet aus dem Firmen-Modell. Firmen sind ausschließlich die Newsrooms, > unter denen PMs veröffentlicht werden. Die Übermittler-Angabe („übermittelt > von …") wird eine **Profil-Eigenschaft des einliefernden Accounts**. > Geplanter Umfang: **1 Arbeitstag**. > **Status 08.07.2026: A1–A5 UMGESETZT, Abnahme erfüllt.** Beide > Daten-Commands sind lokal scharf gelaufen (Reports unter > `storage/app/private/migration/`): 4.482 User mit `agency_name` > (93 Mehrfach-Fälle exakt verglichen — der Plan zählte 77 normalisiert —, > 10 Owner-lose nur reportet), 2.607 Agentur-Firmen umtypisiert, > 2.149 soft-gelöscht, 1 geschützter Fall (Zahlungsoptions-/Mitglieds- > Verknüpfung). Beispiel-PM zeigt die Attributions-Zeile aus dem > Profilfeld. Deploy-Runbook (Erst-Einrichtung, Schritt 2) ergänzt. > Offen: nur A6 (nachgelagert). --- ## Ausgangslage (Stand 07.07.2026) **Bereits umgesetzt (07.07.):** Die Legacy-Attributions-Zeile („Original-Inhalt von {Firma} und übermittelt von {Agentur}") ist auf der öffentlichen Detailseite wieder da — aktuell noch über die Legacy-Datenstruktur: - `PressRelease::submittingAgency()` — hasOne auf `companies` (`owner_user_id = user_id` der PM, `type = agency`, ohne PortalScope) - Rendering in `resources/views/web/release-detail.blade.php` (unter dem Pressekontakt-Block), Übersetzungen `web.detail.attribution*` (de/en) - Eager Loading in `ReleaseDetailPageData` + `PressReleasePreviewController` - 3 Tests in `tests/Feature/Web/ReleaseDetailTest.php` (Verteiler, gleichnamig, ohne Agentur) **Datenlage (lokal geprüft 07.07.):** | Fakt | Wert | |---|---| | Agentur-Firmen (`companies.type = agency`, aktiv) | 4.756 | | … davon selbst Newsroom (PMs mit `company_id` = Agentur) | 2.598 (7.963 PMs) | | … mit Pressekontakten | 27 | | … ohne Owner (`owner_user_id IS NULL`) | 10 | | User mit Agentur-Firma | 4.482 | | User mit **mehreren** verschieden benannten Agentur-Firmen | 77 | | connektar: User 14016 (`info@connektar.de`) | Agentur-Firmen 18811 (pe) + 49196 (bp24), 20.830 PMs | **Kernproblem des Ist-Zustands:** Die Agentur ist eine Pseudo-Firma — im Kunden-Panel nicht von echten Firmen unterscheidbar, die Zuordnung (owner_user_id → user_id der PM) versteht niemand, und mehrere Agentur-Firmen pro Account sind mehrdeutig. --- ## Arbeitsregeln - Test-First bei Verhaltensänderungen; Tests gezielt: `php artisan test --compact --filter=` (wir sind im Sail-Container). - Nach PHP-Änderungen: `vendor/bin/pint --dirty --format agent`. - Jeder Schritt = eigener, fokussierter Commit. - Daten-Kommandos immer mit `--dry-run` zuerst; nie überschreibend. - Web-Frontend-Views gehören dem User → Änderungen dort separat committen. --- ## A1 — Profilfeld `users.agency_name` (~30 min) - [x] Migration: `agency_name` (string 190, nullable) auf `users`. - [x] `User`: fillable ergänzen; `UserFactory`-State `withAgency()`. - [x] Kein eigenes Agentur-Logo/Website fürs Erste (bewusst schlank — erweiterbar, wenn gebraucht). ## A2 — Daten-Übernahme Agentur-Firmen → Profil (~1–1,5 h) - [x] Artisan-Command `legacy:migrate-agency-names` (`--dry-run`, Report nach `storage/app/private/migration/`): - Je User mit Agentur-Firma(en): Namen nach `users.agency_name` übernehmen. - **Regel Mehrfach-Fälle (77 User):** zuletzt aktualisierter Datensatz (`updated_at` max) gewinnt; alle Varianten in den Report. - Nie überschreiben, wenn `agency_name` bereits gesetzt. - Die 10 Owner-losen Agentur-Firmen nur reporten (manuelle Sichtung). - [x] Test mit Factories (Einzel-Fall, Mehrfach-Fall, bereits gesetzt). - [x] **Go-Live-Hinweis:** Command in die WS-7-/Deploy-Checkliste aufnehmen (läuft NACH dem Firmen-/User-Import). ## A3 — Attribution auf Profilfeld umstellen (~1 h) - [x] `release-detail.blade.php`: `$agencyName = $release->user?->agency_name` statt `submittingAgency` (Vergleichs-/Fallback-Logik bleibt identisch: Name ≠ Firma → „Original-Inhalt von … und übermittelt von …"; Name = Firma → „Inhalt übermittelt von …"; leer → „Original-Inhalt von …"). - [x] Eager Loading umstellen: `user:id,agency_name` statt `submittingAgency` (`ReleaseDetailPageData`, `PressReleasePreviewController`). - [x] `PressRelease::submittingAgency()` entfernen. - [x] Tests in `ReleaseDetailTest` auf `agency_name` umschreiben; Suite-Ausschnitt grün (`ReleaseDetail`, `PressReleasePreview`). ## A4 — Firmen bereinigen: Typ „Agentur" abschaffen (~1,5 h) - [x] Artisan-Command `companies:retire-agency-type` (`--dry-run`, Report): - Agentur-Firmen **mit** PMs oder Kontakten → `type = company` umtypen (bleiben Newsrooms; 2.598 + 27, Überschneidung möglich). - Agentur-Firmen **ohne** PMs und Kontakte → Soft-Delete (~2.100). Vorher prüfen: keine `company_user`-Mitgliedschaften Dritter, keine `user_payment_option_company`-Verknüpfung — sonst nur umtypen. - [x] Test mit Factories (umtypen, löschen, geschützter Fall). - [x] Command ebenfalls in die Deploy-Checkliste (nach A2!). ## A5 — UI anpassen (~1,5 h) - [x] **Kunden-Panel Profil** (`livewire/customer/profile.blade.php`): neuer Abschnitt „Agentur-Angaben" mit Feld „Agentur-/Verteilername" und Erklärtext: *„Falls Sie Pressemitteilungen im Auftrag Dritter einreichen, erscheint diese Angabe öffentlich als Übermittler unter Ihren Mitteilungen."* Validierung: nullable, max 190. - [x] **Firma anlegen** (`customer/press-kits/create.blade.php`): Typ-Feld entfernen, fest `type = company`. - [x] **Firmen-Übersicht** (`customer/press-kits/index.blade.php`): Typ-Label aus der Meta-Zeile entfernen (nach A4 gibt es nur noch einen Typ). - [x] **Admin** (`admin/companies/create|edit.blade.php`): Typ-Auswahl entfernen; `admin/users/*`: Feld `agency_name` anzeigen/editierbar machen. - [x] Tests: Profil speichert `agency_name`; Firma-Anlegen ohne Typ-Feld. ## A6 — Nachgelagert (NICHT morgen) - `companies.type`-Spalte + `CompanyType`-Enum komplett entfernen (erst wenn A4 produktiv gelaufen und verifiziert ist). - Optional: Agentur-Logo/-Website im Profil, falls die Attributions-Zeile verlinkt werden soll. - Admin-Auswertung „PMs je Übermittler" (Tracking-Wunsch aus dem Konzept, Abschnitt Distribution-Partner). --- ## Abnahme (Ende des Tages) - [x] Beispiel-PM `fuehrende-laufblogger-…` zeigt weiterhin „Original-Inhalt von Trailbloggercamp und übermittelt von connektar.de Presseverteiler" — jetzt aus `users.agency_name`. - [x] Kunden-Panel: Agentur-Name im Profil sichtbar/änderbar; Firmenliste ohne Agentur-Einträge bzw. ohne Typ-Label. - [x] Beide Daten-Commands mit Report gelaufen (lokal), Deploy-Checkliste ergänzt. - [x] Testsuite grün, Pint sauber, Commits je Schritt.