presseportale/dev/archive/agentur-attribution/entwicklungsplan.md
Kevin Adametz 6a4c4d8837 docs: dev-Doku für den Live-Betrieb neu sortiert — Archiv + Betrieb + Roadmap
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>
2026-07-21 07:52:38 +00:00

142 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.