📚 Subscription Sistemi

ULTIMATE KILAVUZ v2

Tüm Bilgiler Tek Sayfada - Master Plan + Settings + Kullanıcı Durumları + Device Hierarchy

📅 2025-12-05 🎯 Basit & Net & Minimal ✅ Production Ready 🔥 v2: Trial Plan Dinamik

🆕 v2 Değişiklikler (Trial Plan Dinamik)

❌ v1 (YANLIŞ)

  • ❌ "7 gün sabit" ifadesi
  • ❌ Trial her zaman otomatik başlar
  • ❌ Hardcode 7 gün

✅ v2 (DOĞRU)

  • ✅ Trial plan yoksa → Trial YOK!
  • ✅ Trial süresi → Plan cycle'dan (7, 14, 30 gün olabilir)
  • ✅ Trial plan'da TEK cycle olacak

💡 Kritik:

is_trial=true olan plan YOKSA trial sistemi devreye GİRMEZ! Plan varsa cycle'daki gün sayısı trial süresidir.

📑 İçindekiler

1️⃣ ULTIMATE Master Plan

🎯 Stratejik Kararlar

✅ Kabul Edilen Kararlar

  • ✅ Trial plan varsa otomatik başlar
  • ✅ Trial süresi → Plan cycle'dan (dinamik)
  • ✅ is_trial checkbox (slug değil)
  • ✅ has_used_trial kontrolü (tek kullanım)
  • ✅ 30 saniye preview (hardcode)
  • ✅ Request-level fresh check (cache yok)
  • ✅ Event-based system (Observer pattern)
  • ✅ Hibrit sistem (Lazy + Cron)

🔧 Teknik Mimari

  • 📦 SubscriptionService (core logic)
  • 🔔 Event System (SubscriptionExpired vb.)
  • ⏱️ Cron Job (expire check, daily)
  • 🎯 Request-level check (stale önleme)
  • 🗄️ Database: 18 field (unified)
  • 🔐 SettingsManagement (tenant-aware)

📋 Settings Yaklaşımı

❌ Reddedilen: tenants.data JSON

  • • Duplicate çözüm
  • • SettingsManagement zaten var
  • • Tenant-aware değil

✅ Kabul: SettingsManagement

  • • Bu iş için tasarlanmış
  • • 3-layer system
  • • Tenant-aware otomatik
  • • Admin UI hazır

💡 3-Layer System

  • 1️⃣ settings_groups (CENTRAL DB) → Grup tanımı
  • 2️⃣ settings (CENTRAL DB) → Setting tanımı + default_value
  • 3️⃣ settings_values (TENANT DB) → Tenant'a özel değer

2️⃣ Settings (SADECE 2 AYAR - Minimal Yaklaşım)

1

auth_subscription

Ücretli Üyelik Sistemi (Ana Anahtar - Trial Dahil)

Setting ID

211

Type

select

Values

0 / 1

Muzibu Status

1 (AKTİF)

📋 Ne Yapar?

  • 1 (Açık): Subscription modülü aktif → Trial plan varsa otomatik başlar, Premium kontrolleri çalışır
  • 0 (Kapalı): Subscription modülü tamamen kapalı → Herkes sınırsız kullanır (free model)

🔥 v2 Önemli Değişiklik:

Bu ayar 1 OLSA BİLE trial planı yoksa trial başlamaz! Trial plan (is_trial=true) olmalı.

2

auth_device_limit

Cihaz Limit Kontrolü (Global Fallback)

Setting ID

212

Type

number

Default

1

Önerilen

1-3 arası

📋 Ne Yapar?

  • 📱 Global Fallback: User ve Plan'da device_limit yoksa bu değer kullanılır (son çare)
  • 🔢 3-Layer Hierarşi: user.device_limitplan.device_limitauth_device_limit (setting)

💡 Detaylı Bilgi:

Detaylı hiyerarşi için Device Limit Hierarchy bölümüne bak

3️⃣ Hardcode Değerler (SADECE 30 SANİYE)

🎵

30 Saniye Preview Duration

Abonelik yoksa veya biterse müzik 30 saniye çalışır (Guest & Expired kullanıcılar)

const PREVIEW_DURATION = 30; // saniye

✅ Neden Hardcode?

Bu değer değişmeyecek, ayar olarak yönetmeye gerek yok. Kullanıcı: "muzibu 30 saniye kuralı kalıcı değiştirmeye gerek yok. hardcode olsun"

🔥 v2: Çıkarılan Hardcode'lar

❌ "7 gün trial" (v1'de vardı)

Artık hardcode değil, trial plan'ın cycle'ından gelir (dinamik)

❌ "Otomatik trial başlatma" (v1'de vardı)

Trial plan varsa başlar, yoksa başlamaz (koşullu)

🆕 Trial Plan Sistemi (v2)

🎯 Nasıl Çalışır?

1️⃣ Trial Plan Kontrolü

$trialPlan = SubscriptionPlan::where('is_trial', true)
  ->where('is_active', true)
  ->first();

if (!$trialPlan) {
  // Trial sistemi yok, direkt return
  return null;
}

Kritik: is_trial=true olan plan yoksa trial sistemi çalışmaz!

2️⃣ Trial Süresi Hesaplama

$cycles = $trialPlan->billing_cycles; // JSON decode
$firstCycle = array_values($cycles)[0];
$trialDays = $firstCycle['duration_days']; // 7, 14, 30 vs.

Dinamik: Trial plan'ın cycle'ında yazılan gün sayısı kullanılır (7, 14, 30 olabilir)

3️⃣ Trial Plan Yapısı (Örnek JSON)

{
  "subscription_plan_id": 1,
  "title": {"tr": "Deneme", "en": "Trial"},
  "slug": "deneme",
  "is_trial": true,
  "is_active": true,
  "billing_cycles": {
    "deneme-7-gun": {
      "name": {"tr": "7 Günlük Deneme"},
      "duration_days": 7,
      "price": 0
    }
  }
}

Önemli: Trial plan'da SADECE 1 cycle olmalı (deneme süresi)

📝 Örnek Senaryolar

✅ Trial Plan Var (7 gün)

is_trial: true

cycle duration_days: 7

SONUÇ: 7 gün trial verilir

✅ Trial Plan Var (14 gün)

is_trial: true

cycle duration_days: 14

SONUÇ: 14 gün trial verilir

❌ Trial Plan Yok

is_trial=true plan: BULUNAMADI

auth_subscription: 1 (açık olsa bile)

SONUÇ: Trial sistemi YOK

✅ Trial Plan Var (30 gün)

is_trial: true

cycle duration_days: 30

SONUÇ: 30 gün trial verilir

4️⃣ Kullanıcı Durumları (4 Durum)

👤

GUEST (Misafir)

Kayıt olmamış, siteyi gezinen kullanıcı

Dinleme:

30 saniye

Özellikler:

Playlist ❌ | Favori ❌

CTA:

"Sınırsız dinlemek için üye ol!"

🆓

TRIAL (Deneme Üyesi)

Yeni kayıt, trial plan süresince deneme (7-30 gün)

Dinleme:

Sınırsız (X gün)

Özellikler:

Playlist ✅ | Favori ✅

CTA:

"X gün kaldı, Premium'a geç!"

🔥 v2: Dinamik Süre

Trial süresi trial plan'ın cycle'ındaki duration_days değeridir (7, 14, 30 vs.)

👑

PREMIUM (Ücretli Üye)

Ödeme yapmış, aktif premium aboneliği var

Dinleme:

Sınırsız (Ömür boyu)

Özellikler:

TÜM Özellikler ✅

CTA:

"Premium üyesiniz, keyifle dinleyin!"

EXPIRED (Süresi Bitmiş)

Trial veya Premium süresi dolmuş, ödeme yapılmamış

Dinleme:

30 saniye

Özellikler:

Playlist ❌ | Favori ❌

CTA:

"Aboneliğiniz sona erdi! HEMEN YENİLE!"

📊 Hızlı Referans Tablosu

Durum Dinleme Süre Playlist CTA
👤 GUEST 30 saniye - Üye ol
🆓 TRIAL Sınırsız 7-30 gün (plan'dan) Premium'a geç
👑 PREMIUM Sınırsız Ömür boyu Keyifle dinle
⏰ EXPIRED 30 saniye - HEMEN YENİLE!

5️⃣ Device Limit Hierarchy (3-Layer Fallback)

🎯 Nasıl Çalışır?

1️⃣ user.device_limit
En yüksek öncelik (VIP, Test, Ban kullanıcıları için override)
2️⃣ plan.device_limit
Plan'ın default değeri (Normal kullanıcılar için)
3️⃣ auth_device_limit
Global fallback (Son çare, setting)

💡 Mantık:

Üstten alta inerken ilk NULL OLMAYAN değer kullanılır. NULL ise bir sonraki katmana geç.

💻 Kod İmplementasyonu

public function getDeviceLimit(User $user): int
{
  // 1. User override (özel durumlar - VIP/Test/Ban)
  if ($user->device_limit !== null) {
    return $user->device_limit;
  }

  // 2. Plan default (normal akış - çoğu kullanıcı buradan)
  $sub = $user->activeSubscription();
  if ($sub && $sub->plan->device_limit) {
    return $sub->plan->device_limit;
  }

  // 3. Global fallback (son çare - setting)
  return setting('auth_device_limit', 1);
}

⚡ Hızlı Özet (v2 - Trial Dinamik)

📋 ULTIMATE Master Plan

  • ✅ Trial plan varsa otomatik başlar
  • ✅ Trial süresi → Plan cycle'dan (DİNAMİK)
  • ✅ is_trial checkbox
  • ✅ has_used_trial kontrolü
  • ✅ 30 saniye preview
  • ✅ Request-level check
  • ✅ SettingsManagement (3-layer)

⚙️ Settings (2 Adet)

  • 1️⃣ auth_subscription (0/1)
  •    → Ana anahtar (trial plan gerekli!)
  • 2️⃣ auth_device_limit (number)
  •    → Global fallback

🔧 Hardcode (1 Adet)

  • 1️⃣ 30 saniye - Preview süresi
  • ❌ 7 gün (v1) → DİNAMİK (v2)
  • ❌ Auto-start (v1) → KOŞULLU (v2)

🆕 Trial Plan (v2)

  • is_trial=true plan gerekli
  • ✅ Plan yoksa trial YOK
  • ✅ Süre: cycle'dan duration_days
  • ✅ Tek cycle (7, 14, 30 gün vs.)

👥 Kullanıcı (4 Durum)

  • 👤 GUEST - 30 saniye
  • 🆓 TRIAL - X gün (plan'dan)
  • 👑 PREMIUM - Ömür boyu
  • EXPIRED - 30 saniye

📱 Device Hierarchy

  • 1️⃣ user.device_limit - Öncelikli
  • 2️⃣ plan.device_limit - Normal
  • 3️⃣ auth_device_limit - Fallback