Das System ist seit 20.07.2026 live; die dev-Doku spiegelt jetzt den Betriebszustand statt der Release-Vorbereitung: - dev/betrieb/: Deploy-Runbook (neu: §10 Betrieb nach Go-Live mit SFTP-Deploy-Checkliste inkl. queue:restart-Pflicht und den Betriebs-Erkenntnissen der Go-Live-Woche), Legacy-API-Parität, Umami. - dev/roadmap.md: offene Nachlauf-Punkte (Go-Live-Mails, Merge nach main, Stripe-Test-Artefakte, Key-Rotation, Alt-System-Abschaltung) und Ideen-Backlog. - dev/archive/: abgeschlossene Phasen — Migration-2026-Planung, Cutover-Runbook (mit Erledigt-Vermerk), Release-Plan/QA-Checkliste, Optimierungsphasen, Frontend-Konzepte + Responsive-Audits vom 16.07., Altsystem-Reste. - dev/README.md als Wegweiser; gitignore-Pfad der SQL-Dumps mitgezogen (dev/archive/migration-2026/sql/ bleibt untracked, ebenso dev/migration/ und dev/api/). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
142 lines
6.9 KiB
Markdown
142 lines
6.9 KiB
Markdown
# 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=<Name>` (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.
|