presseportale/docs/user-admin/user-zusammenhaenge.md
Kevin Adametz 8d8d957884 Doku: Status-Sync 11./12.06., Decision-Update Preisstruktur und Phase-9-Plan
- Decision-Update Preisstruktur & Veroeffentlichungs-Flow aufgenommen
  (Launch-Tarife, Slot-Verbrauch bei Veroeffentlichung, Submit-Gate,
  Launch-Credits) inkl. Klarstellung 12.06.: Gelb geht direkt live,
  keine manuelle Pruef-Queue, nur Rot wird abgelehnt
- Alle Status-Dokumente auf den Code-Stand gezogen: README-Index,
  STATUS-ABGLEICH (KI-Pipeline, Bilder/Lizenzen, Pricing), Checkliste
  (KI- und Titelbild-Bloecke, Launch-To-dos), Admin-User,
  user-zusammenhaenge (Datenmodell-Delta), Entwicklungsplan KI-Pruefung
  (Phase 0 abgehakt, Decision-Abgleich)
- Ueberschriebene Tarif-Abschnitte in Konzept-Update 1/2 und
  Relaunch-Konzept mit Superseded-/IST-Hinweisen markiert
- Neues Plan-Dokument PHASE-9-FLOW-UND-TARIFE-PLAN.md (9A-9J)
- Phase-8-Roadmap-Doku (20-PHASE-8-USER-PANEL.md) + PROGRESS-Eintraege

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:20:22 +00:00

329 lines
16 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.

# User-Admin: Zusammenhänge und relevante Daten
Stand: 2026-06-11 (aktualisiert nach Phase 8 + KI-Pipeline)
Diese Notiz beschreibt den User als fachlichen Mittelpunkt für die weitere Konzeption des Admin-User-Bereichs. Grundlage sind die aktuellen Models und Migrationen im Laravel-Projekt.
> **Was seit Phase 8 + KI-Pipeline dazugekommen ist (29.05.11.06.2026)**:
>
> - `press_releases`: `placeholder_variant` (SVG-Titelbild-Platzhalter, 8G),
> `classification`/`classified_at` (KI-Klassifikation Rot/Gelb/Grün),
> `content_score`/`content_tier`/`scored_at` (Content-Score).
> - `press_release_images`: Lizenz-/Rechtefelder `author`, `license_type`,
> `license_detail`, `license_url`, `source_url`, `people_rights_status`,
> `property_rights_status`, `rights_notes`, `persons_consent`,
> `rights_confirmed_at` (8H + Erweiterung 10.06.).
> - `users`: Quota-Stub `press_release_quota` +
> `press_release_quota_used_this_month` (8J; wird vom Tarif-Modul abgelöst).
> - Neue Tabelle `ki_audits` (Modell `KiAudit`, append-only Audit-Log jeder
> KI-Entscheidung) mit Relation `PressRelease::kiAudits()`.
> - Neue Enums: `PressReleasePlaceholder`, `ImageLicenseType`,
> `PressReleaseClassification`, `PressReleaseContentTier`.
> - Neue Services/Jobs: `PressReleaseCoverImage` (Cover-Resolver),
> Treiber-Architektur unter `Services/PressRelease/Classification/` und
> `…/ContentScore/`, Jobs `ClassifyPressRelease`/`ScorePressRelease`
> (Queue `classification`), Konfiguration in `config/scoring.php`.
> - Neue Commands: `press-releases:reset-monthly-quota` (Scheduler, 1. des
> Monats), `classification:work` (Queue-Drain zum Testen).
> - Zeitzonen-Konstante `PressRelease::DISPLAY_TIMEZONE` (Europe/Berlin) mit
> `scheduledAtLocal()`/`embargoAtLocal()` für alle Termin-Anzeigen.
> **Was sich seit dem ursprünglichen Stand (2026-05-05) geändert hat**:
>
> - Pressemitteilungen haben zusätzliche Felder: `subtitle`, `scheduled_at`,
> `embargo_at`, `boilerplate_override`, `no_export` (Phase 7).
> - Neue Tabelle `press_release_attachments` (Modell `PressReleaseAttachment`).
> UI ist temporär deaktiviert (Security-Review), Tabelle und Service
> bleiben aber erhalten.
> - Neuer Service-Layer für PMs: `PressReleaseService` (Status-Übergänge,
> Scheduling-Auflösung), `PressReleaseHtmlSanitizer` (HTMLPurifier-Wrapper),
> `PressReleaseAttachmentStorage`.
> - Neuer Console-Command `php artisan press-releases:publish-scheduled`
> (Scheduler-Intervall 5 Min) veröffentlicht geplante PMs automatisch.
> - Pivot `press_release_contact` bleibt n:m, der Customer-Flow speichert
> aber nur einen Kontakt pro PM und das Feld ist nullable.
## Zentraler Ausgangspunkt
Ein `User` ist nicht nur ein Login-Konto, sondern bündelt im System mehrere fachliche Bereiche:
- Zugang und Status: Name, E-Mail, Verifikation, Passwort, 2FA, Aktiv/Inaktiv, Super-Admin-Flag, Rollen/Berechtigungen.
- Portal- und Legacy-Zuordnung: `portal`, `registration_type`, `language`, `legacy_portal`, `legacy_id`.
- CRM-Zuordnung: Firmen, Firmenrollen, Kontakte.
- Content-Zuordnung: Pressemitteilungen, Bilder, Statusverlauf.
- Abrechnung und Verträge: Rechnungsadresse, Zahlungsoptionen, Zahlungen, Rechnungen, Legacy-Rechnungen.
- API und Sicherheit: Sanctum-Tokens, API-Nutzung, Magic-Links.
- Kommunikation und Arbeitskomfort: Newsletter-Abos, Filter-Presets.
## Datenmodell im Überblick
```mermaid
erDiagram
users ||--o| profiles : "hat"
users ||--o| billing_addresses : "hat"
users ||--o{ companies : "owner_user_id"
users }o--o{ companies : "company_user.role"
users }o--o{ contacts : "contact_user"
companies ||--o{ contacts : "hat"
users ||--o{ press_releases : "autor"
companies ||--o{ press_releases : "zugeordnet"
contacts }o--o{ press_releases : "press_release_contact"
press_releases ||--o{ press_release_images : "hat"
press_releases ||--o{ press_release_status_logs : "hat"
users ||--o{ press_release_status_logs : "changed_by_user_id"
users ||--o{ user_payment_options : "hat"
user_payment_options }o--o{ companies : "user_payment_option_company"
user_payment_options ||--o{ user_payments : "hat"
user_payments ||--o{ invoices : "erzeugt"
users ||--o{ invoices : "hat"
users ||--o{ legacy_invoices : "hat"
users ||--o{ newsletter_subscriptions : "hat"
users ||--o{ magic_links : "hat"
users ||--o{ user_filter_presets : "hat"
users ||--o{ api_usage_logs : "hat"
```
## Direkte Relationen am User
`profile`
- Kardinalität: 1:0..1.
- Tabelle: `profiles`, Foreign Key `user_id` ist eindeutig.
- Inhalt: persönliche Profildaten, Anrede, Titel, Vor-/Nachname, Telefon, Adresse, Land, Geburtsdatum, Backlink, Statistik-/Footer-Code-Flags, Validierungs-/Vertragsdaten, Steuerdaten.
- Relevanz im Admin: Datenqualität, Legacy-Profil, persönliche Stammdaten, Vertrag/Validierung.
`billingAddress`
- Kardinalität: 1:0..1.
- Tabelle: `billing_addresses`, Foreign Key `user_id` ist eindeutig.
- Inhalt: Rechnungsname, Adresse, PLZ, Ort, Land.
- Relevanz im Admin: Rechnungsfähigkeit, fehlende Abrechnungsdaten, Kundendatenpflege.
`ownedCompanies`
- Kardinalität: 1:n.
- Tabelle: `companies`, Foreign Key `owner_user_id`.
- Bedeutung: Der User ist fachlicher Eigentümer einer Firma, auch ohne Pivot-Eintrag in `company_user`.
- Relevanz im Admin: wichtig für Rechte im Customer-Profil und für klare Verantwortlichkeit.
`companies`
- Kardinalität: n:m.
- Pivot: `company_user` mit `company_id`, `user_id`, `role`.
- Rollen: `member`, `responsible`, `owner`.
- Bedeutung: Ein User kann mehrere Firmen haben; eine Firma kann mehreren Usern zugeordnet sein.
- Relevanz im Admin: Hauptstruktur für Kundenkonto, Berechtigungen in der Firmenpflege und spätere User-Detailansicht.
`contacts`
- Kardinalität: n:m.
- Pivot: `contact_user` mit `contact_id`, `user_id`.
- Zusätzlich gehört jeder Kontakt zwingend zu genau einer Firma über `contacts.company_id`.
- Bedeutung: Kontakte können direkt Usern zugeordnet sein, fachlich sind sie aber an Firmen aufgehängt.
- Relevanz im Admin: Ansprechpartner und Zuordnungsqualität.
`pressReleases`
- Kardinalität: 1:n.
- Tabelle: `press_releases`, Foreign Key `user_id`.
- Zusätzlich: optionale Firmenzuordnung über `company_id` und Pflichtkategorie über `category_id`.
- Wichtig: Datenbankseitig ist `company_id` nullable, fachlich sollte eine Customer-PM einer Firma zugeordnet sein. Der Customer-Flow erzwingt aktuell eine eigene Firma und leitet daraus das Portal ab.
- Relevanz im Admin: Content-Historie, Status, Veröffentlichungen, Qualität, Freigabeprozess.
`newsletterSubscriptions`
- Kardinalität: 1:n.
- Tabelle: `newsletter_subscriptions`, Foreign Key `user_id`.
- Inhalt: Portal, Name, E-Mail, IP, Bestätigung, Subscribe/Unsubscribe, Legacy-Zuordnung.
- Relevanz im Admin: Kommunikationsstatus und Opt-in/Opt-out-Historie.
`billing / payments`
- `userPaymentOptions`: 1:n über `user_payment_options.user_id`.
- `invoices`: 1:n über `invoices.user_id`.
- `legacyInvoices`: 1:n über `legacy_invoices.user_id`.
- Indirekt: `user_payment_options` hat n:m zu Firmen über `user_payment_option_company`; `user_payments` hängt an `user_payment_options`; `invoices` können zusätzlich an `user_payments` und `invoice_billing_addresses` hängen.
- Relevanz im Admin: Vertrags-/Abo-Status, aktive API-Freischaltung, Rechnungen, Legacy-Archiv.
`tokens`
- Kommt über Laravel Sanctum `HasApiTokens`.
- Tabelle: `personal_access_tokens` mit polymorphem `tokenable_type` / `tokenable_id`.
- Im Customer-Bereich werden Tokens für API-Zugriffe verwaltet.
- Relevanz im Admin: API-Zugang, genutzte Berechtigungen, letzter Zugriff.
`magicLinks`
- Kardinalität: 1:n.
- Tabelle: `magic_links`, Foreign Key `user_id`.
- Inhalt: Token-Hash, Zweck, Payload, Ablauf, Verbrauch, IPs.
- Relevanz im Admin: Auth-/Support-Kontext, Magic-Login-Historie.
`filterPresets`
- Kardinalität: 1:n.
- Tabelle: `user_filter_presets`, Foreign Key `user_id`.
- Inhalt: Seite, Name, Default-Flag, letzte Nutzung, Filter-JSON.
- Relevanz im Admin: eher Arbeitskomfort/Personalisierung, nicht Kern-Kundendaten.
`apiUsageLogs`
- Kardinalität: faktisch 1:n über `api_usage_logs.user_id`, aber aktuell keine Relation im `User`-Model.
- Inhalt: Token, Methode, Pfad, Route, Status, IP, User-Agent, Dauer, Zeitpunkt.
- Relevanz im Admin: API-Aktivität, Support und Missbrauchsanalyse.
`roles` und `permissions`
- Kommen über Spatie `HasRoles`.
- Tabellen u. a. `roles`, `permissions`, `model_has_roles`, `model_has_permissions`, `role_has_permissions`.
- Relevanz im Admin: Trennung zwischen Admin, Editor, Customer, Super-Admin und feineren Berechtigungen wie `press-releases:publish` oder `users:manage`.
## Firmen, Kontakte und Pressemitteilungen
Die fachliche CRM-/Content-Struktur läuft im Kern so:
- User hat mehrere Firmen über `company_user`.
- User kann zusätzlich direkter Eigentümer einer Firma über `companies.owner_user_id` sein.
- Firma hat mehrere Kontakte über `contacts.company_id`.
- Firma hat mehrere Pressemitteilungen über `press_releases.company_id`.
- Pressemitteilung hat genau einen Autor/User über `press_releases.user_id`.
- Pressemitteilung kann mehrere Kontakte über `press_release_contact` referenzieren.
- Kontakt kann mehreren Usern direkt zugeordnet sein über `contact_user`, bleibt aber immer an genau eine Firma gebunden.
Daraus ergibt sich für den User-Admin eine wichtige Sicht:
- User-Zentrum: Wer ist der Account?
- Firmen-Zentrum: Welche Firmen gehören dazu, in welcher Rolle?
- Kontakt-Zentrum: Welche Ansprechpartner hängen an diesen Firmen und/oder am User?
- Content-Zentrum: Welche Pressemitteilungen wurden vom User erstellt und welcher Firma sind sie zugeordnet?
- Abrechnungs-Zentrum: Welche Zahloptionen, Rechnungen und Legacy-Rechnungen hängen am User und ggf. an Firmen?
## Pressemitteilungen im Detail
Eine Pressemitteilung (`press_releases`) enthält:
- Identifikation: `id`, `uuid`, `slug`, `legacy_portal`, `legacy_id`.
- Zuordnung: `portal`, `language`, `user_id`, `company_id`, `category_id`.
- Inhalt: `title`, `subtitle`, `text`, `backlink_url`, `keywords`, `boilerplate_override`.
- Status/Publikation: `status`, `published_at`, `scheduled_at`, `embargo_at`, `no_export`, `hits`, `teaser_begin`, `teaser_end`.
- Medien: Bilder über `press_release_images`, Anhänge über `press_release_attachments` (UI deaktiviert).
- Kontakte: Pivot `press_release_contact`.
- Verlauf: Statuslogs über `press_release_status_logs`, inklusive `changed_by_user_id`, Statuswechsel, Grund und Quelle.
Service-Layer rund um PMs:
- `App\Services\PressRelease\PressReleaseService` — kapselt die Übergänge `submitForReview`, `publish`, `reject`, `archive`, `deleteFromAdmin` sowie das Auflösen von `scheduled_at`/`embargo_at` für die echte Veröffentlichung.
- `App\Services\PressRelease\PressReleaseHtmlSanitizer` — Wrapper um `mews/purifier` mit definierter Tag-/Attribut-Whitelist.
- `App\Services\PressRelease\PressReleaseAttachmentStorage` — kapselt Datei-Operationen auf dem `public`-Disk (UI aktuell deaktiviert).
- `App\Console\Commands\PublishScheduledPressReleases` — wird per Scheduler (alle 5 Min) ausgeführt und veröffentlicht freigegebene PMs zum geplanten Zeitpunkt, respektiert Embargo.
Fachliche Konsequenz:
- Für Kunden sollte `company_id` praktisch Pflicht sein, obwohl die DB es nullable erlaubt.
- Für Admins kann `company_id = null` als Migrations-/Altfall auftauchen und sollte im User-Admin sichtbar markiert werden.
- `portal` sollte mit der Firma konsistent sein. Im Customer-Flow wird das Portal aus der Firma abgeleitet; im Admin-Bereich sollte eine bewusste Korrektur möglich sein.
## User-relevante Tabellen
Kernkonto:
- `users`
- `profiles`
- `billing_addresses`
- `sessions`
- `password_reset_tokens`
- `personal_access_tokens`
- `magic_links`
- Spatie Permission-Tabellen
CRM:
- `companies`
- `company_user`
- `contacts`
- `contact_user`
Content:
- `press_releases`
- `press_release_images`
- `press_release_attachments` (UI temporaer deaktiviert)
- `press_release_contact`
- `press_release_status_logs`
- `categories`
- `category_translations`
Billing:
- `billing_addresses`
- `user_payment_options`
- `user_payment_option_company`
- `user_payments`
- `payment_options`
- `payment_option_translations`
- `invoices`
- `invoice_billing_addresses`
- `legacy_invoices`
Kommunikation/API/Arbeitskomfort:
- `newsletter_subscriptions`
- `api_usage_logs`
- `user_filter_presets`
## Relevante Inhalte für den Admin-User-Bereich
Für eine optimierte Admin-User-Ansicht sollten diese Blöcke geplant werden:
- Account: Status, Portal, Sprache, Registrierungstyp, Rollen, Berechtigungen, Super-Admin, letzte Aktivität, letzte IP, E-Mail-Verifikation, 2FA-Status.
- Datenqualität: Profil vorhanden, Rechnungsadresse vorhanden, Firma vorhanden, Kontakte vorhanden, veröffentlichte PMs vorhanden, Legacy-Zuordnung vorhanden.
- Firmen: Firmenliste mit Rolle, Eigentümerstatus, Portal, Aktivstatus, Logo, Footer-Code-Flag, Kontakt-/PM-Anzahl.
- Kontakte: Kontakte je Firma plus direkte User-Kontakte aus `contact_user`.
- Pressemitteilungen: Gesamtzahl, Statusverteilung, letzte PMs, veröffentlichte PMs, PMs ohne Firma, PMs mit Portalabweichung.
- Abrechnung: Rechnungsadresse, aktive Zahlungsoptionen, verknüpfte Firmen zu Zahlungsoptionen, Zahlungen, Rechnungen, Legacy-Rechnungen.
- API: Token-Anzahl, Berechtigungen, letzte Nutzung, API-Usage-Logs.
- Support/Admin-Aktionen: User bearbeiten, Rollen/Berechtigungen ändern, Impersonation, Magic-Link-Kontext, ggf. Account deaktivieren.
## Offene Punkte für die weitere Konzeption
- `User` hat keine direkte `apiUsageLogs()`-Relation, obwohl `api_usage_logs.user_id` existiert. Für Admin-Detailansichten wäre eine Relation sinnvoll.
- `press_releases.company_id` ist nullable. Fachlich sollte geklärt werden, ob das nur Legacy-/Admin-Fälle erlaubt oder langfristig verboten werden soll.
- `contacts` gehören immer zu einer Firma, können aber zusätzlich direkt Usern zugeordnet werden. Für die Oberfläche muss klar sein, ob "User-Kontakte" nur direkte Pivot-Kontakte meint oder alle Kontakte seiner Firmen.
- Eine Firma kann über `owner_user_id` und zusätzlich über `company_user.role = owner` eine Eigentümerinformation haben. Das sollte im Admin eindeutig dargestellt und ggf. harmonisiert werden.
- Billing hängt primär am User, Zahlungsoptionen können aber über Pivot auch Firmen betreffen. Für den Admin sollte klar werden, ob Rechnungen immer User-Rechnungen sind oder später firmenscharf betrachtet werden sollen.
- Portal-Scope ist auf Firmen, Kontakte, Pressemitteilungen und Newsletter aktiv. Admin-Auswertungen nutzen teils `withoutGlobalScopes()`. In der User-Admin-Konzeption muss entschieden werden, wann portalübergreifend gesucht und angezeigt wird.
## Quellen im Code
Modelle:
- `app/Models/User.php`
- `app/Models/Company.php`
- `app/Models/Contact.php`
- `app/Models/PressRelease.php`
- `app/Models/PressReleaseImage.php`
- `app/Models/PressReleaseAttachment.php`
- `app/Models/PressReleaseStatusLog.php`
- `app/Models/Profile.php`
- `app/Models/BillingAddress.php`
- `app/Models/Invoice.php`
- `app/Models/LegacyInvoice.php`
- `app/Models/UserPaymentOption.php`
- `app/Models/UserPayment.php`
- `app/Models/NewsletterSubscription.php`
- `app/Models/MagicLink.php`
- `app/Models/UserFilterPreset.php`
- `app/Models/ApiUsageLog.php`
Services / Commands:
- `app/Services/PressRelease/PressReleaseService.php`
- `app/Services/PressRelease/PressReleaseHtmlSanitizer.php`
- `app/Services/PressRelease/PressReleaseAttachmentStorage.php`
- `app/Services/Image/ImageService.php`
- `app/Console/Commands/PublishScheduledPressReleases.php`
- `routes/console.php` (Scheduler-Eintraege)
Migrationen:
- `database/migrations/*`