Zum Hauptinhalt springen

User & Notification Models

Diese Domäne umfasst Benutzer, Workspaces, Favoriten sowie das zweistufige Benachrichtigungssystem (Announcements + Notifications) mit Quiet Hours und Präferenzen.

User

Benutzer-Model mit WorkOS SSO-Integration. Dispatcht bei Erstellung das UserRegistered-Event.

Tabelle: users

FeldTypNullableBeschreibung
idbigintPKPrimary Key
namestringneinAnzeigename
emailstringneinE-Mail-Adresse (unique)
workos_idstringjaWorkOS SSO-Identifier
avatarstringjaAvatar-URL
timezonestringjaZeitzone (Default: Europe/Berlin)
email_verified_atdatetimejaE-Mail verifiziert am
passwordstringjaPasswort (hashed)
remember_tokenstringjaRemember-Me-Token
newsletter_opted_in_atdatetimejaNewsletter-Bestaetigung (Double-Opt-In)
newsletter_tokenvarchar(64)jaToken fuer Newsletter-Bestaetigung
newsletter_token_expires_atdatetimejaToken-Ablauf (7 Tage)
privacy_accepted_atdatetimejaDatenschutz-Zustimmung bei Registrierung
terms_accepted_atdatetimejaAGB-Zustimmung bei Registrierung
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
workspaces()hasManyWorkspaceowner_idEigene Workspaces
notificationPreferences()hasManyNotificationPreferenceuser_idBenachrichtigungs-Einstellungen
quietHours()hasOneUserQuietHoursuser_idRuhezeiten
notifications()morphManyDatabaseNotificationnotifiable_idPer-User Notifications

Hidden: workos_id, remember_token, newsletter_token

Casts: email_verified_at → datetime, password → hashed, newsletter_opted_in_at → datetime, newsletter_token_expires_at → datetime, privacy_accepted_at → datetime, terms_accepted_at → datetime

Accessors: timezone -- gibt Europe/Berlin zurück falls kein Wert gesetzt.

Boot-Event:

static::created(function (User $user) {
UserRegistered::dispatch($user->id, $user->name, $user->email, $user->avatar);
});

Methoden:

MethodeReturnBeschreibung
initials()stringInitialen aus dem Namen
isAdmin()boolPrüft ob E-Mail in config('postbox.admin_emails')
visibleNotifications()MorphManyNotifications mit accessibleBy() Scope
unreadNotificationsCount()intAnzahl ungelesener, sichtbarer Notifications
visibleAnnouncements()BuilderAnnouncements per forUser() Scope
unreadAnnouncements()BuilderUngelesene Announcements
hasNewsletterSubscription()boolNewsletter bestaetigt (newsletter_opted_in_at IS NOT NULL)
hasNewsletterPending()boolToken existiert, aber nicht bestaetigt

Location: app/Models/User.php


Workspace

Container für Watchers. Jeder User kann mehrere Workspaces haben. Der Admin-Workspace (ID 999999999999) spiegelt automatisch alle Profile.

Tabelle: workspaces

FeldTypNullableBeschreibung
idbigintPKPrimary Key
owner_idbigint (FK)neinBesitzer-User
namestringneinWorkspace-Name
descriptiontextjaBeschreibung
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
owner()belongsToUserowner_idBesitzer
watchers()hasManyWatcherworkspace_idWatchers im Workspace

Admin-Workspace: ID 999999999999 (AdminWorkspaceManager::ADMIN_WORKSPACE_ID), wird per watchers:backfill-admin-workspace stündlich aktualisiert.

Location: app/Models/Workspace.php


FavoriteSocialProfile

Favorisierte Profile eines Users. Unique-Constraint auf (user_id, social_profile_id).

Tabelle: favorite_social_profiles

FeldTypNullableBeschreibung
idbigintPKPrimary Key
user_idbigint (FK)neinUser
social_profile_idbigint (FK)neinFavorisiertes Profil
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
user()belongsToUseruser_idZugehöriger User
profile()belongsToSocialProfilesocial_profile_idFavorisiertes Profil

Location: app/Models/FavoriteSocialProfile.php


UserQuietHours

Ruhezeiten-Konfiguration pro User. Steuert, wann Benachrichtigungen unterdrückt werden. Pro Wochentag aktivier-/deaktivierbar.

Tabelle: user_quiet_hours

FeldTypNullableBeschreibung
idbigintPKPrimary Key
user_idbigint (FK)neinZugehöriger User (unique)
enabledbooleanneinRuhezeiten aktiviert
window_startstringneinStart-Uhrzeit (z.B. 22:00)
window_endstringneinEnd-Uhrzeit (z.B. 08:00)
mondaybooleanneinMontag aktiv
tuesdaybooleanneinDienstag aktiv
wednesdaybooleanneinMittwoch aktiv
thursdaybooleanneinDonnerstag aktiv
fridaybooleanneinFreitag aktiv
saturdaybooleanneinSamstag aktiv
sundaybooleanneinSonntag aktiv
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
user()belongsToUseruser_idZugehöriger User

Casts: enabled → boolean, monday...sunday → boolean

Methoden:

MethodeReturnBeschreibung
isCurrentlyQuiet()boolPrüft ob gerade Ruhezeit ist
nextActiveTime()CarbonNächster Zeitpunkt nach Ruhezeit
activeDayLabels()arrayLabels der aktiven Tage

Location: app/Models/UserQuietHours.php


NotificationPreference

Benachrichtigungs-Einstellungen pro User und Workspace. Steuert App- und E-Mail-Kanal pro Notification-Typ.

Tabelle: notification_preferences

FeldTypNullableBeschreibung
idbigintPKPrimary Key
user_idbigint (FK)neinZugehöriger User
workspace_idbigint (FK)jaZugehöriger Workspace (null = global)
notification_typestringneinTyp (z.B. daily_scrape, import_completed)
channel_appbooleanneinIn-App-Kanal aktiviert
channel_emailbooleanneinE-Mail-Kanal aktiviert
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
user()belongsToUseruser_idZugehöriger User
workspace()belongsToWorkspaceworkspace_idZugehöriger Workspace

Methoden: isChannelEnabled($channel) -- prüft ob ein bestimmter Kanal aktiviert ist.

Location: app/Models/NotificationPreference.php


NotificationStat

Aggregierte Statistiken für Benachrichtigungen. Upsert-Counter per Tag, Kanal und Typ.

Tabelle: notification_stats

FeldTypNullableBeschreibung
idbigintPKPrimary Key
datedateneinTag
channelstringneinKanal (app, email)
typestringneinNotification-Typ
countintegerneinAnzahl
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Casts: date → date, count → integer

Methoden: record($channel, $type) (static) -- Upsert-Increment auf dem aktuellen Tag.

Location: app/Models/NotificationStat.php


Announcement

Geteilte Benachrichtigungen (1 Zeile pro Event, Read-Tracking über AnnouncementRead). Unterstützt Audience-Targeting und Ablaufzeiten.

Tabelle: announcements

FeldTypNullableBeschreibung
idbigintPKPrimary Key
typestringneinAnnouncement-Typ
datajsonneinPayload (title, body, icon, url)
admin_onlybooleanneinNur für Admins sichtbar
audience_typestringjauser, workspace, all
audience_idintegerjaZiel-ID (User-ID oder Workspace-ID)
expires_atdatetimejaAblaufzeitpunkt
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Relations:

MethodeTypRelated ModelFKBeschreibung
reads()hasManyAnnouncementReadannouncement_idRead-/Dismiss-Status

Scopes:

ScopeBeschreibung
forUser($user)Announcements sichtbar für diesen User
notExpired()Nur nicht-abgelaufene
visibleTo($user)Admin-Only-Filter
notDismissedBy($user)Nicht dismissed
unreadBy($user)Ungelesene

Casts: data → array, admin_only → boolean, expires_at → datetime, audience_id → integer

Methoden: isReadBy($user), isUnreadBy($user), markAsReadBy($user), isExpired(), getTitle(), getBody(), getUrl(), getIcon()

Location: app/Models/Announcement.php


AnnouncementRead

Read-/Dismiss-Status pro User und Announcement. Composite Primary Key ohne Auto-Increment.

Tabelle: announcement_reads

FeldTypNullableBeschreibung
user_idbigint (FK)PKUser-ID
announcement_idbigint (FK)PKAnnouncement-ID
read_atdatetimejaGelesen am
dismissed_atdatetimejaDismissed am

Relations:

MethodeTypRelated ModelFKBeschreibung
user()belongsToUseruser_idLesender User
announcement()belongsToAnnouncementannouncement_idZugehörige Announcement

Timestamps: false (kein created_at/updated_at)

Casts: read_at → datetime, dismissed_at → datetime

Location: app/Models/AnnouncementRead.php


DatabaseNotification

Erweitert Laravels BaseDatabaseNotification um expires_at und admin_only. Per-User Notifications (im Gegensatz zu Announcements, die geteilt werden).

Tabelle: notifications

FeldTypNullableBeschreibung
iduuidPKUUID Primary Key
typestringneinNotification-Klasse
notifiable_typestringneinPolymorphe Typ-Spalte
notifiable_idbigintneinPolymorphe ID-Spalte
datajsonneinNotification-Payload
read_atdatetimejaGelesen am
admin_onlybooleanneinNur für Admins sichtbar
expires_atdatetimejaAblaufzeitpunkt
created_atdatetimeneinErstellt am
updated_atdatetimeneinAktualisiert am

Scopes:

ScopeBeschreibung
notExpired()expires_at IS NULL OR expires_at > NOW()
visibleTo($user)Admin-Only-Filter basierend auf $user->isAdmin()
accessibleBy($user)Kombination: visibleTo() + notExpired()

Casts: data → array, read_at → datetime, expires_at → datetime, admin_only → boolean

Methoden: isExpired()

Location: app/Models/DatabaseNotification.php