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

16 KiB
Raw Permalink Blame History

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

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/*