Dashboard & Explore Models
Diese Domäne umfasst die aggregierten Metriken für das Dashboard (Rollups, Sync-Tracking) sowie die Explore-Features (Trending, Growth, Kategorien, Cross-Platform).
DashboardDailyRollup
Aggregierte Tagesmetriken pro Profil, gruppiert nach Owner, Workspace und Watcher. Basis für die Dashboard-Charts und Leaderboards. Wird per dashboard:rollup-daily-metrics (täglich 00:45 UTC) befüllt.
Tabelle: dashboard_daily_rollups
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
date | date | nein | Datum des Rollups |
owner_id | bigint (FK) | nein | User-ID des Workspace-Owners |
workspace_id | bigint (FK) | nein | Workspace-ID |
watcher_id | bigint (FK) | nein | Watcher-ID |
social_profile_id | bigint (FK) | nein | Profil-ID |
followers_count | bigint | ja | Follower/Subscriber-Anzahl |
view_count | bigint | ja | Aufrufe (YouTube) |
video_count | integer | ja | Anzahl Videos (YouTube) |
comment_count | bigint | ja | Kommentare (YouTube) |
following_count | integer | ja | Following (Instagram) |
post_count | integer | ja | Posts (Instagram) |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Casts: date → date
Hinweis: Der Rollup enthält keine Relations, da die Daten per Query Builder aggregiert werden. Die Tabelle wird per Command dashboard:rollup-daily-metrics aus social_profile_daily_metrics befüllt.
Location: app/Models/DashboardDailyRollup.php
DailyScrapeProgress
Fortschritt des täglichen Scrapings pro User. Wird genutzt, um dem User Feedback zum Sync-Fortschritt seiner Profile zu geben. Löst DailyScrapeCompleted-Event bei 100% aus.
Tabelle: daily_scrape_progress
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
user_id | bigint (FK) | nein | Zugehöriger User |
date | date | nein | Scrape-Datum |
expected_count | integer | nein | Erwartete Profile |
completed_count | integer | nein | Erfolgreich gescrapte |
failed_count | integer | nein | Fehlgeschlagene |
notification_sent | boolean | nein | Benachrichtigung bereits versandt |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Relations:
| Methode | Typ | Related Model | FK | Beschreibung |
|---|---|---|---|---|
user() | belongsTo | User | user_id | Zugehöriger User |
Casts: date → date, notification_sent → boolean
Methoden: isComplete() -- prüft ob completed_count + failed_count >= expected_count
Location: app/Models/DailyScrapeProgress.php
DailySyncRun
Status eines täglichen Sync-Durchlaufs. Wird vom ExploreMetricsCalculator genutzt, um "complete" Sync-Tage als Datengrundlage zu identifizieren.
Tabelle: daily_sync_runs
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
date | date | nein | Sync-Datum (unique) |
expected_profiles | integer | nein | Erwartete Profile |
processed_profiles | integer | nein | Verarbeitete Profile |
failed_profiles | integer | nein | Fehlgeschlagene |
status | string | nein | running, completed, failed |
finished_at | datetime | ja | Abschluss-Zeitpunkt |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Casts: date → date, finished_at → datetime
Status-Werte:
| Status | Beschreibung |
|---|---|
running | Sync läuft noch |
completed | Erfolgreich abgeschlossen |
failed | Fehlgeschlagen |
Methoden: latestCompleteDate() (static) -- gibt das neueste Datum zurück, an dem der Sync vollständig war.
Location: app/Models/DailySyncRun.php
ExploreProfileMetric
Berechnete Explore-Metriken pro Profil. Enthält Growth-Daten (1d/7d/30d), Trending-Score, Tier-Klassifizierung und Flags wie is_rising_star. Wird per explore:calculate (täglich 03:00 UTC) aktualisiert.
Tabelle: explore_profile_metrics
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
social_profile_id | bigint (FK) | nein | Zugehöriges Profil (unique) |
followers_count | bigint | ja | Aktuelle Follower-Anzahl |
followers_growth_1d | bigint | ja | Absolutes Wachstum 1 Tag |
followers_growth_7d | bigint | ja | Absolutes Wachstum 7 Tage |
followers_growth_30d | bigint | ja | Absolutes Wachstum 30 Tage |
followers_growth_pct_1d | float | ja | Prozentuales Wachstum 1 Tag |
followers_growth_pct_7d | float | ja | Prozentuales Wachstum 7 Tage |
followers_growth_pct_30d | float | ja | Prozentuales Wachstum 30 Tage |
trending_score | float | ja | Aktueller Trending-Score |
previous_trending_score | float | ja | Vorheriger Trending-Score |
growth_score | float | ja | Wachstums-Score |
consistency_score | float | ja | Konsistenz-Score |
follower_tier | string | ja | micro, small, medium, large, mega |
primary_category | string | ja | Hauptkategorie |
detected_tags | json | ja | Erkannte Tags (Array) |
is_rising_star | boolean | ja | Überdurchschnittliches Wachstum im Tier |
is_new | boolean | ja | Neu in Explore |
is_trending | boolean | ja | Aktuell trendend |
trending_calculated_at | datetime | ja | Letzte Trending-Berechnung |
daily_calculated_at | datetime | ja | Letzte tägliche Berechnung |
weekly_calculated_at | datetime | ja | Letzte wöchentliche Berechnung |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Relations:
| Methode | Typ | Related Model | FK | Beschreibung |
|---|---|---|---|---|
socialProfile() | belongsTo | SocialProfile | social_profile_id | Zugehöriges Profil |
Scopes:
| Scope | Beschreibung |
|---|---|
minFollowers($count) | Minimum Follower-Anzahl |
tier($tier) | Nach Follower-Tier filtern |
risingStars() | Nur Rising Stars |
newProfiles() | Nur neue Profile |
Konstanten:
MIN_FOLLOWERS_FOR_EXPLORE = 100
TIER_BOUNDARIES = [
'micro' => [0, 10_000],
'small' => [10_000, 100_000],
'medium' => [100_000, 500_000],
'large' => [500_000, 1_000_000],
'mega' => [1_000_000, PHP_INT_MAX],
]
Accessors: tier_label, formatted_growth_7d
Methoden: calculateTier() (static)
Location: app/Models/ExploreProfileMetric.php
ExploreTrendingVideo
Trending-Videos für die Explore-Seite. Enthält Velocity- und Trending-Scores basierend auf View-Growth über verschiedene Zeiträume.
Tabelle: explore_trending_videos
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
social_profile_id | bigint (FK) | nein | Zugehöriger Channel |
video_id | string | nein | YouTube Video-ID |
title | string | ja | Video-Titel |
thumbnail_url | string | ja | Thumbnail-URL |
channel_title | string | ja | Channel-Name |
duration_seconds | integer | ja | Dauer in Sekunden |
view_count | bigint | ja | Aktuelle Views |
like_count | bigint | ja | Aktuelle Likes |
view_growth_1h | bigint | ja | View-Wachstum letzte Stunde |
view_growth_24h | bigint | ja | View-Wachstum 24 Stunden |
view_growth_7d | bigint | ja | View-Wachstum 7 Tage |
velocity_score | float | ja | Velocity-Score (Views/Zeiteinheit) |
trending_score | float | ja | Trending-Score |
published_at | datetime | ja | Veröffentlichungsdatum |
calculated_at | datetime | ja | Letzte Berechnung |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Relations:
| Methode | Typ | Related Model | FK | Beschreibung |
|---|---|---|---|---|
socialProfile() | belongsTo | SocialProfile | social_profile_id | Zugehoeriger Channel |
video() | belongsTo | YouTubeVideo | video_id | YouTube-Video-Record (fuer R2-Thumbnails, Tags) |
latestScore() | hasOne | YouTubeVideoScore | youtube_video_id | Neuester Video-Score |
Scopes:
| Scope | Beschreibung |
|---|---|
publishedWithin($days) | Videos veröffentlicht in X Tagen |
trending() | Nach Trending-Score sortiert |
Accessors: engagement_rate, url, formatted_duration, formatted_views, formatted_growth_24h
Location: app/Models/ExploreTrendingVideo.php
ExploreCategory
Kategorien für die Explore-Seite. Enthält Keywords und YouTube-Kategorie-IDs für automatisches Matching.
Tabelle: explore_categories
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
slug | string | nein | URL-Slug (unique) |
name | string | nein | Englischer Name |
name_de | string | ja | Deutscher Name |
icon | string | ja | Emoji-Icon fuer UI-Anzeige |
keywords | json | ja | Zugehörige Keywords (Array) |
youtube_category_ids | json | ja | YouTube-Kategorie-IDs (Array) |
profile_count | integer | nein | Anzahl zugeordneter Profile |
sort_order | integer | nein | Sortierreihenfolge |
is_active | boolean | nein | Aktiv/Sichtbar |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Scopes:
| Scope | Beschreibung |
|---|---|
active() | Nur aktive Kategorien |
ordered() | Nach sort_order sortiert |
Casts: keywords → array, youtube_category_ids → array, profile_count → integer, sort_order → integer, is_active → boolean
Accessors: localized_name -- gibt name_de zurück falls vorhanden, sonst name.
Location: app/Models/ExploreCategory.php
ExploreDailySnapshot
Taegliche Explore-Inventar-Snapshots mit Statistiken zur Bestandsentwicklung. Wird durch pipeline:run (taeglich 01:00 UTC) befuellt.
Tabelle: explore_daily_snapshots
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
date | date | nein | Snapshot-Datum (unique) |
total_profiles | integer | ja | Gesamtzahl Profile in Explore |
youtube_count | integer | ja | YouTube Profile |
instagram_count | integer | ja | Instagram Profile |
tier_mega | integer | ja | Mega Tier (1M+) |
tier_large | integer | ja | Large Tier (500k-1M) |
tier_medium | integer | ja | Medium Tier (100k-500k) |
tier_small | integer | ja | Small Tier (10k-100k) |
tier_micro | integer | ja | Micro Tier (0-10k) |
trending_count | integer | ja | Trending Profile Count |
rising_stars_count | integer | ja | Rising Stars Count |
categorized_count | integer | ja | Kategorisierte Profile |
new_profiles_count | integer | ja | Neue Profile |
avg_trending_score | float | ja | Durchschnittlicher Trending-Score |
created_at | datetime | nein | Erstellt am |
Hinweis: $timestamps = false — nur created_at wird befuellt, kein updated_at.
Casts: date → date:Y-m-d, avg_trending_score → float, created_at → datetime
Location: app/Models/ExploreDailySnapshot.php
CrossPlatformRelatedProfile
Plattformuebergreifende Profil-Verknuepfungen (z.B. ein YouTuber und sein Instagram-Account). Wird durch pipeline:run (taeglich 01:00 UTC) befuellt.
Tabelle: cross_platform_related_profiles
| Feld | Typ | Nullable | Beschreibung |
|---|---|---|---|
id | bigint | PK | Primary Key |
source_profile_id | bigint (FK) | nein | Quell-Profil |
related_profile_id | bigint (FK) | nein | Verknuepftes Profil (andere Plattform) |
relevance_score | integer | ja | Relevanz (0-100) |
match_reason | string | ja | Grund der Verknuepfung |
cross_profile_verified_at | datetime | ja | Admin-Verifizierungszeitpunkt |
cross_profile_verified_by | bigint (FK) | ja | Admin-User-ID der Verifizierung |
created_at | datetime | nein | Erstellt am |
updated_at | datetime | nein | Aktualisiert am |
Relations:
| Methode | Typ | Related Model | FK | Beschreibung |
|---|---|---|---|---|
sourceProfile() | belongsTo | SocialProfile | source_profile_id | Quell-Profil |
relatedProfile() | belongsTo | SocialProfile | related_profile_id | Verknuepftes Profil |
verifiedByUser() | belongsTo | User | cross_profile_verified_by | Verifizierender Admin |
Scopes: verified() — nur admin-verifizierte Verknuepfungen.
Methoden: isVerified() — prueft ob Verknuepfung von Admin verifiziert wurde.
Casts: relevance_score → integer, cross_profile_verified_at → datetime
Location: app/Models/CrossPlatformRelatedProfile.php