🎵 Muzibu Trial System

MASTER PLAN - Tenant 1001 Özel

📅 Tarih: 2025-12-04 🎵 Tenant: 1001 (muzibu.com) 💾 DB: tenant_muzibu_1528d0 🎯 Hedef: Gerçek Zamanlı Trial Kontrolü

🔍 MEVCUT SİSTEM ANALİZİ (Tenant 1001)

⚠️ KRİTİK BULGULAR:
  • isPremium() metodu 1 SAAT cache kullanıyor! (User.php:411)
  • SongStreamController isPremium() kullanıyor (cached!)
  • users.has_used_trial field YOK! (eklenecek)
  • subscription_plans.is_trial field YOK! (eklenecek)

📊 Database Yapısı (Central DB: tuufi_4ekim)

✅ MEVCUT (Kullanılabilir)

  • subscriptions tablosu VAR
  • subscription_plans tablosu VAR
  • users tablosu VAR
  • subscriptions.status → active, trial, expired, cancelled
  • subscriptions.current_period_end → Bitiş tarihi
  • subscriptions.has_trial, trial_days, trial_ends_at VAR
  • subscription_plans.trial_days VAR (plan seviyesi)

❌ EKSİK (Eklenecek)

  • users.has_used_trial field YOK → Migration gerekli!
  • subscription_plans.is_trial boolean YOK → Migration gerekli!

💻 Kod Analizi (Mevcut Durum)

📍 User.php:400-425 - isPremium() Metodu // 🚨 SORUN: 1 saatlik cache! $cacheKey = 'user_' . $this->id . '_is_premium_tenant_1001'; return Cache::remember($cacheKey, 3600, function () { $activeSubscription = $this->subscriptions() ->where('status', 'active') ->where('current_period_end', '>', now()) ->first(); return $activeSubscription ? true : false; });

❌ Cache kullanıyor → Trial bitince 1 saat geç fark edilir!

📍 User.php:432-451 - isTrialActive() Metodu public function isTrialActive(): bool { $trialSubscription = $this->subscriptions() ->where('status', 'trial') ->whereNotNull('trial_ends_at') ->where('trial_ends_at', '>', now()) ->first(); return $trialSubscription ? true : false; }

✅ Cache YOK, direkt DB kontrolü (İYİ!)

📍 SongStreamController.php:98 - Stream Endpoint // Normal üye (premium değil) → 30 saniye preview if (!$user->isPremium()) { // Preview ver }

❌ Cached isPremium() kullanıyor → Fresh check gerekli!

⚠️ Subscription Model (Subscription.php)

  • scopeActive() → status='active' ve current_period_end > now()
  • scopeTrial() → status='trial'
  • scopeExpired() → status='expired'
  • Status enum: active, trial, expired, cancelled, paused, pending_payment

❌ TEK SORUN: Gerçek Zamanlı Kontrol Eksikliği

🚨 ANA PROBLEM:
  • Kullanıcı 1 kere giriş yapar → 5 yıl çıkış yapmaz!
  • isPremium() 1 saat cache → Trial bitince geç fark edilir!
  • Stream endpoint cached metod kullanıyor!
  • Trial bitince → Hala sınırsız dinliyor (AYLAR BOYU!)
  • Premium bitince → Ücretsiz kullanmaya devam ediyor!

📋 3 Kritik Senaryo:

❌ Senaryo 1: Trial Bitişi

  • Gün 0-7: Trial kullanıyor
  • Gün 8: Trial bitti
  • Cache: 1 saat daha premium!
  • Gün 9-∞: Hala dinliyor!

Kayıp: SONSUZ

❌ Senaryo 2: Cache Gecikmesi

  • 00:00: Premium bitti
  • 00:00-01:00: Cache sayesinde hala premium!
  • 01:00: Yeni cache oluştu, yine 1 saat!
  • Sonuç: Her müzik çalışta 1 saat gecikmeli!

Kayıp: 1 SAAT/İSTEK

✅ ORTAK ÇÖZÜM: 3 Katmanlı Sistem

💡 TEK PRENSİP

Request-Level Fresh Check + Event-Based System + Cron Backup
Her müzik isteğinde gerçek zamanlı kontrol, durum değişince event fırlat, yedek cron!

❌ ESKİ SİSTEM

  • isPremium() → 1 saat cache
  • Stream endpoint → Cached metod
  • Lazy check → Giriş/çıkış bekler
  • Trial cycle bazında (karışık)
  • Sonuç: Aylar boyu ücretsiz!

✅ YENİ SİSTEM

  • isPremiumFresh() → CACHE YOK!
  • Stream endpoint → Fresh metod
  • Request-level → Her müzik isteğinde
  • Trial ayrı plan (is_trial checkbox)
  • Sonuç: 0 saniye gecikmeli kontrol!

⚙️ İMPLEMENTASYON - 4 Faz (Tenant 1001)

Faz 1: Database & Model (Foundation)

YÜKSEK ÖNCELİK
  • 1
    Migration: users.has_used_trial ekle (Central DB)

    database/migrations/YYYY_MM_DD_add_has_used_trial_to_users.php
    Boolean field, default false, index ekle

  • 2
    Migration: subscription_plans.is_trial ekle (Central DB)

    database/migrations/YYYY_MM_DD_add_is_trial_to_subscription_plans.php
    Boolean field, default false, unique constraint (sadece 1 plan is_trial=true)

  • 3
    User.php: isPremiumFresh() metodu ekle

    app/Models/User.php
    isPremium()'i kopyala ama Cache KULLANMA! Direkt DB check
    Tenant 1001 kontrolü ekle: if (!$this->isMuzibuTenant()) return false;

  • 4
    SubscriptionPlan model: is_trial fillable ekle

    Modules/Subscription/app/Models/SubscriptionPlan.php
    $fillable'a 'is_trial' ekle, $casts'a 'is_trial' => 'boolean'

Faz 2: Event System (Core Logic)

YÜKSEK ÖNCELİK
  • 5
    Event: TrialExpired oluştur

    app/Events/TrialExpired.php
    Properties: $user, $subscription

  • 6
    Event: SubscriptionExpired oluştur

    app/Events/SubscriptionExpired.php

  • 7
    Listener: SendTrialExpiredEmail + Log + Notification

    app/Listeners/SendTrialExpiredEmail.php
    Email gönder, push bildirim, log tut, analytics

  • 8
    isPremiumFresh() içine event dispatch ekle

    Subscription bittiyse → Status güncelle (active → expired)
    Event fırlat: event(new TrialExpired($user, $subscription))

  • 9
    EventServiceProvider'a listener'ları kaydet

    app/Providers/EventServiceProvider.php
    $listen array'ine event-listener mapping'leri ekle

Faz 3: Stream Endpoint (Real-time Control)

YÜKSEK ÖNCELİK
  • 10
    SongStreamController: isPremiumFresh() kullan

    Modules/Muzibu/app/Http/Controllers/Api/SongStreamController.php:98
    if (!$user->isPremium())if (!$user->isPremiumFresh())

  • 11
    HLS Playlist endpoint: Fresh check ekle

    Dynamic playlist controller'ında da isPremiumFresh() kullan
    Her chunk isteğinde kontrol et

  • 12
    API Middleware: SubscriptionCheck (opsiyonel)

    app/Http/Middleware/CheckSubscription.php
    Tüm API route'larına eklenebilir, otomatik expire check

Faz 4: Admin Panel & Trial Setup

ORTA ÖNCELİK
  • 13
    Admin Panel: Trial planı oluştur (Manuel)

    Subscription Plans → Yeni Plan
    Title: "Trial", slug: "trial", fiyat: ₺0.00, süre: 7 gün
    is_trial checkbox'ı işaretle

  • 14
    subscription-plan-manage UI: Trial field'ları kaldır

    Modules/Subscription/.../subscription-plan-manage-component.blade.php
    7 lokasyon: Cycle card badge, Edit modal input, New modal input

  • 15
    Kayıt: Otomatik trial subscription oluştur

    RegisterController'da:
    1. has_used_trial kontrol et
    2. False ise trial plan bul (is_trial = true)
    3. Subscription oluştur, has_used_trial = true yap

  • 16
    Cron Job: Günlük yedek temizlik

    app/Console/Kernel.php
    Siteye girmeyen kullanıcıların expired subscription'larını temizle

🗺️ ROADMAP - Sıralama (Tenant 1001)

📋 16 Adım - Öncelik Sırası:
# Görev Dosya/Konum Öncelik
1 Migration: users.has_used_trial database/migrations/ YÜKSEK
2 Migration: subscription_plans.is_trial database/migrations/ YÜKSEK
3 User.php: isPremiumFresh() ekle app/Models/User.php YÜKSEK
4 SubscriptionPlan: is_trial fillable Modules/Subscription/.../SubscriptionPlan.php YÜKSEK
5 Event: TrialExpired oluştur app/Events/TrialExpired.php YÜKSEK
6 Event: SubscriptionExpired oluştur app/Events/SubscriptionExpired.php YÜKSEK
7 Listener'lar oluştur app/Listeners/ YÜKSEK
8 isPremiumFresh() event dispatch app/Models/User.php YÜKSEK
9 EventServiceProvider kayıt app/Providers/EventServiceProvider.php YÜKSEK
10 SongStreamController: Fresh check Modules/Muzibu/.../SongStreamController.php:98 YÜKSEK
11 HLS Playlist: Fresh check Modules/Muzibu/.../DynamicPlaylistController.php YÜKSEK
12 Middleware: SubscriptionCheck (opsiyonel) app/Http/Middleware/ ORTA
13 Admin: Trial planı oluştur (manuel) Admin Panel → Subscription Plans ORTA
14 Admin UI: Trial field temizle ...subscription-plan-manage-component.blade.php ORTA
15 Register: Otomatik trial subscription RegisterController veya User boot() ORTA
16 Cron: Günlük yedek temizlik app/Console/Kernel.php DÜŞÜK

🎯 SON KARAR (Tenant 1001)

⚡ 3 KATMANLI SİSTEM

1️⃣ Request-Level Fresh Check

Her müzik isteğinde isPremiumFresh() çağır → CACHE YOK!
Tenant 1001 kontrolü: if (!$this->isMuzibuTenant()) return false;

2️⃣ Event-Based System

Subscription bittiyse → Status güncelle (active → expired)
Event fırlat → Listener'lar çalışır (email, log, bildirim)

3️⃣ Cron Backup

Günlük toplu temizlik (siteye girmeyenler için)
Sadece yedek amaçlı, asıl kontrol request-level

⚠️ KRİTİK KURALLAR (Tenant 1001):
  • ASLA cache kullanma stream endpoint'lerde!
  • Her müzik isteğinde isPremiumFresh() çağır!
  • Event dispatch et subscription bittiğinde!
  • Tenant 1001 kontrolü her metodda yap!
  • Central DB kullan (users, subscriptions, subscription_plans)
  • Giriş/çıkış bekleme! Kullanıcı 5 yıl girmeyebilir!
✅ SONUÇ:
  • ✅ Trial bitince 0 saniye gecikmeli kontrol
  • ✅ Cache YOK → Gerçek zamanlı
  • ✅ Event-based → Otomatik email/bildirim
  • ✅ Tenant-aware → Sadece Muzibu'ya özel
  • ✅ 16 adım roadmap → Net sıralama
  • ✅ Mevcut sistem analizi → Hatasız implementation