Problem Tanımı
Basit Anlatım (Herkes İçin)
Ne oluyor? Kullanıcı siteye girdiğinde her yerde "Premium Üye" olarak görünüyor. Ancak bir şarkıya tıkladığında aniden "Ücretsiz Üye" olarak değişiyor ve "Premium'a Geç" butonu çıkıyor.
Nasıl anlaşılıyor? Aynı kullanıcı, aynı anda, aynı sayfada hem premium hem ücretsiz görünüyor. Sol menüde taç var ama şarkı çalamıyor.
Örnek Senaryo:
- Kullanıcı siteye giriş yapıyor
- Sol menüde altın taç simgesi ve "Premium Üye" yazısı görüyor
- Bir şarkıya tıklıyor
- Aniden "Premium üyelik gerekli" uyarısı çıkıyor
- Kullanıcı şaşkın: "Ben zaten premium değil miyim?"
Teknik Detaylar (Geliştiriciler İçin)
Sistemde premium kontrolü yapan birden fazla farklı yöntem kullanılıyor. Her yöntem farklı kaynaklardan veri okuyor ve bazıları stale (eski) veri döndürüyor.
Tutarsız Olan:
- Model property (stale olabilir)
- Subscription relationship
- Trial ayrı kontrolü
- Cache'lenmiş veri
Tek Kaynak Olmalı:
- users.subscription_expires_at
- Fresh DB kontrolü
- Merkezi isPremium() metodu
Etkilenen Alanlar
Sol Sidebar
Kullanıcı avatar'ı yanındaki premium rozeti ve üyelik tipi yazısı
Header Menüsü
"Premium'a Geç" butonu ve premium badge gösterimi
Dashboard
Üyelik durumu kartı ve kalan süre gösterimi
CTA Banner
Premium teşvik banner'ı (3 farklı senaryo)
Müzik Çalar API
Şarkı stream endpoint'i premium kontrolü
Middleware
Route bazlı premium koruma katmanı
Kök Neden Analizi
Çoklu Kontrol Yöntemi
Sistemde premium kontrolü için birden fazla farklı yöntem kullanılıyor. Her bileşen kendi yöntemini kullanıyor ve bunlar birbiriyle uyumsuz olabiliyor.
Kullanılan Yöntemler:
- Model Property: $user->subscription_expires_at (stale olabilir)
- Relationship: $user->subscription() (ayrı sorgu)
- Trial Kontrolü: isTrialActive() (ayrı mantık)
- Service: SubscriptionService::checkUserAccess()
Stale Model Verisi
Sayfa yüklendiğinde User modeli bir kez yükleniyor. Ancak AJAX çağrılarında veya API isteklerinde model yeniden yüklenmiyor. Bu durumda eski (stale) veri kullanılabiliyor.
Senaryo:
- Sayfa yüklenir, User modeli okunur (subscription_expires_at: 2026-02-01)
- Sidebar bu değeri okur → Premium gösterir
- API isteği yapılır, farklı bir kontrol mekanizması devreye girer
- API fresh DB kontrolü yapar ama farklı koşul kullanır
- Sonuç: İki farklı yerde iki farklı durum
Trial ve Premium Ayrımı
Sistemde "trial" ve "premium" kavramları ayrı ayrı kontrol ediliyor. Bazı yerlerde sadece premium kontrol edilirken, bazı yerlerde trial ayrıca kontrol ediliyor.
Problem:
- Sidebar: isPremium() kullanıyor
- API: subscription status = 'active' kontrol ediyor
- Trial kullanıcı API'da aktif görünmüyor
Mevcut Kontrol Noktaları Haritası
| Dosya | Satır | Kontrol Yöntemi | Kaynak | Durum |
|---|---|---|---|---|
| User.php | 380-398 | isPremium() | Fresh DB + Model | Doğru |
| sidebar.blade.php | 58-82 | auth()->user()->isPremium() | Model metodu | Doğru |
| header.blade.php | 623-677 | currentUser?.is_premium (JS) | Alpine.js store | Kontrol Et |
| dashboard.blade.php | 32-70 | $user->isPremium() | Controller'dan gelen | Doğru |
| SongStreamController.php | 82-102 | $user->isPremium() | Fresh model | Doğru |
| SongStreamController.php | 513-533 | getSubscriptionData() | Fresh DB query | Doğru |
| SubscriptionService.php | 314-356 | checkUserAccess() | subscription_expires_at | Doğru |
| Middleware | 60-86 | subscription_expires_at | Direct check | Doğru |
Çözüm: Tek Kaynak Prensibi (Single Source of Truth)
Hedef Mimari
Tek Kaynak:
users.subscription_expires_at
- Tarih gelecekte ise = Premium
- Tarih geçmişte veya NULL = Ücretsiz
- Trial ayrımı yok (trial da premium sayılır)
Tek Metod:
User::isPremium()
- Her yerde bu metod kullanılmalı
- Fresh DB kontrolü yapmalı
- Request-level cache olabilir
Uygulanacak Değişiklikler
User::isPremium() metodunu merkezi yap
Tüm premium kontrollerini bu metoda yönlendir
Header Alpine.js store'u güncelle
is_premium değerini backend'den doğru şekilde al
Trial kontrollerini kaldır
isTrialActive(), isPremiumOrTrial() metodlarını deprecate et
API response tutarlılığı sağla
Tüm API'larda aynı is_premium değerini döndür
İncelenmesi Gereken Dosyalar
Backend
- app/Models/User.php
- Modules/Subscription/app/Services/SubscriptionService.php
- Modules/Muzibu/app/Http/Controllers/Api/SongStreamController.php
- Modules/Muzibu/app/Http/Middleware/CheckPremiumSubscription.php
- Modules/Muzibu/app/Services/DeviceService.php
Frontend (Blade)
- resources/views/themes/muzibu/components/header.blade.php
- resources/views/themes/muzibu/components/sidebar.blade.php
- resources/views/themes/muzibu/components/sidebar-left.blade.php
- resources/views/themes/muzibu/dashboard.blade.php
- resources/views/themes/muzibu/components/subscription/cta-banner.blade.php