- 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>
16 KiB
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-/Rechtefelderauthor,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-Stubpress_release_quota+press_release_quota_used_this_month(8J; wird vom Tarif-Modul abgelöst).- Neue Tabelle
ki_audits(ModellKiAudit, append-only Audit-Log jeder KI-Entscheidung) mit RelationPressRelease::kiAudits().- Neue Enums:
PressReleasePlaceholder,ImageLicenseType,PressReleaseClassification,PressReleaseContentTier.- Neue Services/Jobs:
PressReleaseCoverImage(Cover-Resolver), Treiber-Architektur unterServices/PressRelease/Classification/und…/ContentScore/, JobsClassifyPressRelease/ScorePressRelease(Queueclassification), Konfiguration inconfig/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) mitscheduledAtLocal()/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(ModellPressReleaseAttachment). 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_contactbleibt 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 Keyuser_idist 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 Keyuser_idist eindeutig. - Inhalt: Rechnungsname, Adresse, PLZ, Ort, Land.
- Relevanz im Admin: Rechnungsfähigkeit, fehlende Abrechnungsdaten, Kundendatenpflege.
ownedCompanies
- Kardinalität: 1:n.
- Tabelle:
companies, Foreign Keyowner_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_usermitcompany_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_usermitcontact_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 Keyuser_id. - Zusätzlich: optionale Firmenzuordnung über
company_idund Pflichtkategorie übercategory_id. - Wichtig: Datenbankseitig ist
company_idnullable, 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 Keyuser_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 überuser_payment_options.user_id.invoices: 1:n überinvoices.user_id.legacyInvoices: 1:n überlegacy_invoices.user_id.- Indirekt:
user_payment_optionshat n:m zu Firmen überuser_payment_option_company;user_paymentshängt anuser_payment_options;invoiceskönnen zusätzlich anuser_paymentsundinvoice_billing_addresseshängen. - Relevanz im Admin: Vertrags-/Abo-Status, aktive API-Freischaltung, Rechnungen, Legacy-Archiv.
tokens
- Kommt über Laravel Sanctum
HasApiTokens. - Tabelle:
personal_access_tokensmit polymorphemtokenable_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 Keyuser_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 Keyuser_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 imUser-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:publishoderusers: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_idsein. - 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_contactreferenzieren. - 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 überpress_release_attachments(UI deaktiviert). - Kontakte: Pivot
press_release_contact. - Verlauf: Statuslogs über
press_release_status_logs, inklusivechanged_by_user_id, Statuswechsel, Grund und Quelle.
Service-Layer rund um PMs:
App\Services\PressRelease\PressReleaseService— kapselt die ÜbergängesubmitForReview,publish,reject,archive,deleteFromAdminsowie das Auflösen vonscheduled_at/embargo_atfür die echte Veröffentlichung.App\Services\PressRelease\PressReleaseHtmlSanitizer— Wrapper ummews/purifiermit definierter Tag-/Attribut-Whitelist.App\Services\PressRelease\PressReleaseAttachmentStorage— kapselt Datei-Operationen auf dempublic-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_idpraktisch Pflicht sein, obwohl die DB es nullable erlaubt. - Für Admins kann
company_id = nullals Migrations-/Altfall auftauchen und sollte im User-Admin sichtbar markiert werden. portalsollte 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:
usersprofilesbilling_addressessessionspassword_reset_tokenspersonal_access_tokensmagic_links- Spatie Permission-Tabellen
CRM:
companiescompany_usercontactscontact_user
Content:
press_releasespress_release_imagespress_release_attachments(UI temporaer deaktiviert)press_release_contactpress_release_status_logscategoriescategory_translations
Billing:
billing_addressesuser_payment_optionsuser_payment_option_companyuser_paymentspayment_optionspayment_option_translationsinvoicesinvoice_billing_addresseslegacy_invoices
Kommunikation/API/Arbeitskomfort:
newsletter_subscriptionsapi_usage_logsuser_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
Userhat keine direkteapiUsageLogs()-Relation, obwohlapi_usage_logs.user_idexistiert. Für Admin-Detailansichten wäre eine Relation sinnvoll.press_releases.company_idist nullable. Fachlich sollte geklärt werden, ob das nur Legacy-/Admin-Fälle erlaubt oder langfristig verboten werden soll.contactsgehö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_idund zusätzlich übercompany_user.role = ownereine 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.phpapp/Models/Company.phpapp/Models/Contact.phpapp/Models/PressRelease.phpapp/Models/PressReleaseImage.phpapp/Models/PressReleaseAttachment.phpapp/Models/PressReleaseStatusLog.phpapp/Models/Profile.phpapp/Models/BillingAddress.phpapp/Models/Invoice.phpapp/Models/LegacyInvoice.phpapp/Models/UserPaymentOption.phpapp/Models/UserPayment.phpapp/Models/NewsletterSubscription.phpapp/Models/MagicLink.phpapp/Models/UserFilterPreset.phpapp/Models/ApiUsageLog.php
Services / Commands:
app/Services/PressRelease/PressReleaseService.phpapp/Services/PressRelease/PressReleaseHtmlSanitizer.phpapp/Services/PressRelease/PressReleaseAttachmentStorage.phpapp/Services/Image/ImageService.phpapp/Console/Commands/PublishScheduledPressReleases.phproutes/console.php(Scheduler-Eintraege)
Migrationen:
database/migrations/*