1 · Proje Kimliği
Holland, Hollanda'da yaşayan Türk topluluğunun CBR theorie examen'i Türkçe çalışarak ve ilk seferde geçebilmesi için kurulmuş bir SaaS platformudur.
| Marka | HollandRijbewijs |
|---|---|
| Hedef Kitle | Hollanda'da yaşayan Türkler — CBR theorie examen'e Türkçe hazırlanmak isteyenler |
| Dağıtım | Web (mobil uyumlu); ayrı uygulama gerektirmez |
| Hosting | Veri merkezi (PostgreSQL 17 + .NET 8) |
| Teknoloji | ASP.NET Core 8 MVC · PostgreSQL · Hangfire · Tailwind CSS · Tabler (admin) |
| Ödeme & Fatura | Iyzico (3D Secure) · Paraşüt e-Arşiv Fatura |
| Diller | Tamamen Türkçe içerik (UI, video, sorular, açıklamalar) |
2 · Halka Açık Yüz (Public)
Ziyaretçilerin ilk karşılaştığı yüz: hero, akıllı öğrenme bölümü, paketler, ücretsiz deneme testi, kayıt ve giriş.
2.1 Anasayfa — Hero
1000+ Türkçe soru bankası ve örnek soru kartı sağ tarafta — kullanıcı kayıt olmadan platformun tadına bakabiliyor.
Stats bandı: 7+ saat video · 1000+ soru bankası · 4+ kategori · %100 Türkçe. Tüm metinler admin panelinden yönetilebilir.
2.2 Akıllı Öğrenme Bölümü YENİ
Sistemin "neyi farklı yaptığını" anlatan bölüm. Yanlış cevapladığın soruları nasıl takip ettiğimiz, zayıf konuları nasıl daha sık çıkardığımız ve 50 soruluk gerçek sınav simülasyonunda dengeli karışım sunduğumuz görsel olarak anlatılıyor.
2.3 Paketler — Pakete Özel Özellik Listesi YENİ
Her paketin kendine özel özellik listesi vardır; admin panelinden satır satır düzenlenebilir. Anasayfa kartlarındaki bullet'lar artık hardcoded değil — her pakette farklı görünür.
2.4 Paket Özellikleri Admin Yönetimi YENİ
Admin → Paketler → Düzenle ekranında Özellik Listesi textarea'sı: her satır anasayfada bir madde olarak görünür. Boş bırakılırsa standart 4 madde (varsayılan) gösterilir.
Package.CourseId set edilirse kullanıcı sadece o kursa erişebilir. Boş bırakılırsa tüm aktif kurslar açıktır. Erişim kontrolü Student Course/Module/Video/Quiz controller'larında zorunlu.
2.5 Ücretsiz Deneme Testi
Kayıt olmadan denenebilir 10 soruluk akıllı deneme — kullanıcıyı pakete yönlendirmek için stratejik bir sayfa.
2.6 Kayıt Formu — Opsiyonel Sınav Tarihi YENİ
Kullanıcı sınav tarihini paylaşırsa hem sınavdan 1 gün önce başarı dileği, hem 3 gün sonra sonuç anketi maili otomatik gönderilir.
2.7 Giriş
/Admin, Öğrenci → /Student.3 · Otomatik Mail Sistemi YENİ
3 farklı durumda otomatik mail gönderimi. Hepsi Hollanda yerel saatiyle, DST otomatik ayarlı. Şablonlar admin panelden HTML olarak düzenlenebilir.
3.1 Mail Şablonları Admin Sayfası
{AdSoyad}, {SinavTarihi}, {BasariliLink}, {KursUrl}, {OptOutUrl}...).
3.2 Sınavdan 1 Gün Önce — Başarı Dilekleri & Hatırlatma
| Tetik | SinavTarihi == yarın (NL lokal saat) |
|---|---|
| Saat | Amsterdam 12:00 (yaz UTC 10:00, kış UTC 11:00 — DST otomatik) |
| İçerik | Sınava hazırlık tüyoları + nazik motivasyon mesajı |
| Tekrar | Hayır — SinavHatirlatmaGonderildiAt damgalanır |
3.3 Sınavdan 3 Gün Sonra — Sonuç Anketi
| Tetik | SinavTarihi == bugün - 3 (NL lokal saat) |
|---|---|
| Saat | Amsterdam 12:00 |
| İçerik | Tek tıkla "Geçtim ✓" / "Geçemedim ✗" butonları (HMAC imzalı 30 günlük token) |
| Etki | Geçemeyen kullanıcıya otomatik ikinci kur indirim hakkı tanımlanır |
3.4 İnaktif Kullanıcı Hatırlatma (2 günde bir)
| Tetik | Aktif aboneliği var + opt-out etmemiş + 2+ gündür login olmamış + son hatırlatma 2+ gün önce |
|---|---|
| Saat | Amsterdam 18:00 (akşamüstü) |
| İçerik | Doğrudan kurs sayfasına yönlendiren gradient buton + alt kısımda "Bildirimleri kapat" linki (HMAC imzalı 90 günlük token) |
| Spam koruması | Her başarılı gönderimde KursHatirlatmaSonGonderim damgalanır → 2 günden önce 2. mail gitmez. Yeni kullanıcı + hiç login yapmamış + 2 gün geçmemiş → mail gönderilmez. |
KursHatirlatmaKapali=true.3.5 Hesabım — Bildirim Tercihleri
4 · Öğrenci Paneli (Student Area)
Aboneliği aktif kullanıcının video sihirbazı, modül sınavları, gerçek sınav simülasyonu ve hesap yönetimi.
4.1 Vimeo Video Altyapısı 🎬 YENİ
Tüm dersler Vimeo (Standard plan) üzerinden yayınlanır. Holland sunucusunda video saklanmaz; transcoding/storage/bant genişliği maliyeti yoktur.
- Reklamsız — kullanıcı hiçbir koşulda preroll/midroll reklam görmez
- Domain whitelist — videolar sadece
hollandrijbewijs.nlüzerinden oynatılır; link sızsa bile başka yerde çalışmaz - Adaptive bitrate — 240p–4K otomatik kalite ayarı
- Marka temizliği — Vimeo logosu gizlenir
- ToS uyumu — Vimeo zaten ücretli eğitim/membership için pazarlanır
Admin Yönetimi
- Ayarlar → Vimeo sekmesi: Personal Access Token, hesap kullanıcı adı, player renk akzanı (HEX), marka temizliği (logo / başlık / "by username" / avatar toggle), Do-not-track (GDPR)
- "Bağlantıyı Test Et" butonu:
api.vimeo.com/meçağrısı yapar — hesap adı, plan ve toplam video sayısı 1 saniyede döner - Vimeo'ya videoyu yükle → Privacy → "Hide from Vimeo" + "Only specific domains" + sitenin domainini whitelist'le
- Holland Admin → Modül → Video Ekle: Vimeo URL veya ID'yi yapıştır (
vimeo.com/76979871→ otomatik76979871olarak ayıklanır)
Öğrenci tarafı izleme kontrolleri
- İleri alma engellenir — kullanıcı seek bar'a tıklasa bile sistem 1.5 saniyeden fazla sıçramayı geri çeker (sadece pause + play)
- Bölüm indeksi ile istenen noktaya zıplama serbest (seek-back hack devre dışı bırakılır)
- İzleme süresi takibi — her 10 saniyede bir sunucuya heartbeat
- Sunucu tarafı
VideoIzlemetablosunda birikimli süre (azalmaz, hile koruması) - Video'nun %85'ini izlemeyen kullanıcı modül sonu testini açamaz — kilit sunucu tarafında zorunlu
4.2 Eğitimim — Kurs Listesi
4.3 50 Soruluk Gerçek Sınav Simülasyonu YENİ
Kurs detay sayfasının üstüne yerleştirilmiş gradient renkli CTA butonu — tek tıkla CBR formatında 50 soruluk gerçek sınav simülasyonu başlatır.
- Kursun her aktif modülünden eşit kota (50 ÷ N modül + kalan ilk modüllere dağılır)
- Her modül kotasının %50'si kullanıcıların genel olarak yanlış cevapladığı sorulardan (weighted random; yüksek hata oranı 6× ağırlık)
- Kalan %50'si o modülün geri kalan sorularından (yine weighted)
- Geçiş eşiği: %88 (CBR theorie geçiş notuna birebir)
- Kurs havuzu soruları (modüle bağlı olmayan ortak sorular) tüm modüllerde ek havuz olarak kullanılır
4.4 Paket Yükseltme (Upgrade) YENİ 🚀
Aktif aboneliği olan kullanıcı, fiyat farkını ödeyerek üst pakete geçebilir. Gün hesabı yok — sadece "yeni paket − mevcut paket" farkı alınır.
Aboneliklerim sayfasında CTA
Üst Paket Listesi
Sadece aynı kurs tipinde ve daha pahalı paketler listelenir. Her kartta net hesaplama:
Onay Ekranı
- Sadece üst paket — downgrade yok
- Aynı kurs tipi zorunlu (Standart ↔ Standart, Özel Eğitim ↔ Özel Eğitim)
- Gün/prorated hesabı yok — basit "yeni fiyat − eski fiyat = fark"
- Iyzico 3DS ile fark çekilir → eski abonelik
Cancelled→ yeni abonelik tam süre baştan başlar
5 · Admin Paneli (Backoffice)
Tabler tabanlı modern yönetim arayüzü — KPI dashboard, kullanıcı yönetimi, içerik & ayarlar.
5.1 Dashboard YENİ
Üst sıra 4 KPI: Toplam Kullanıcı · Aktif Üye · Pasif Üye · Bu Ay Ciro. Alt sıra 4 KPI: Bekleyen Fatura · Toplam Sınav (anket) · Sınav Geçen · Başarı Oranı %. Altında 12 aylık aylık ciro & satış bar chart.
5.2 Kullanıcılar — Tümü / Aktif / Pasif Sekmeleri YENİ
5.3 Sistem Ayarları
8 sekme içinde tüm sistem yönetilebilir:
| Sekme | İçerik |
|---|---|
| Paraşüt | API anahtarları, müşteri kodu — Paraşüt'ten e-fatura çıkışı için |
| Iyzico | API anahtarları (sandbox / production), callback URL |
| E-posta (SMTP) | Mail sunucu ayarları |
| Site | Marka adı, base URL, WhatsApp numarası |
| Analytics & SEO | Google Tag Manager, sitemap |
| İndirimler | Yenileme indirimi, başarısız sınav indirimi, kullanım kuralları |
| Anasayfa Metinleri | Hero, Stats, Features, Yöntem Bölümü, Steps, Packages, Testimonials, FAQ, CTA, Footer, Cookie |
| Mail Şablonları YENİ | 3 otomatik mail şablonu HTML editörü |
Anasayfa Metinleri → Yöntem Bölümü
6 · Soru Bankası — Esnek Atama YENİ
Bir soru artık birden fazla modüle ve birden fazla kursa ortak olarak atanabilir. Toplu seçimle birlikte yönetim çok hızlandı.
6.1 Çoklu Modül Ataması (N-N)
Bir soru ortak ise (örn. "Kırmızı ışıkta ne yapmalısınız?") aynı anda birden fazla modülde kullanılabilir. Edit sayfasında multi-select ile seçilir, listede mor rozetler ile görünür.
6.2 Kurs Havuzu (Kurs Seviyesinde Ortak Soru) YENİ
Bir soru hiç modüle bağlanmadan doğrudan bir kurs havuzuna atanabilir. Bu sorular o kursun tüm modülleri için ortak bir havuz oluşturur ve simülasyon algoritması bunları da dengeli dahil eder.
6.3 Toplu Seçim & Toplu Atama YENİ
Listede checkbox ile birden fazla soru seçilir. Üstte beliren toolbar'dan "Toplu Atama" modal'ı açılır: 3 mod (Ekle / Değiştir / Çıkar) + Modüller + Kurs Havuzu çoklu seçimleri.
- Modüller (N-N) — belirli modül(ler)e ait konu-spesifik sorular
- Kurs Havuzu (N-N) — modülden bağımsız, kurs seviyesinde ortak sorular
- Toplu atama — listede çoklu seçim + Ekle/Değiştir/Çıkar moduyla saniyeler içinde yüzlerce soruya atama yapılır
7 · Güvenlik & Üretim Kalitesi
4 bağımsız uzman incelemesi (Project / UI / Backend / Security admin) — kritik bulgu sıfır.
7.1 Yapılan Sıkılaştırmalar
| Konu | Uygulama |
|---|---|
| IOptions cache | 3 mail job'ı IOptionsSnapshot<T> kullanır; admin'den şablon değişikliği sonraki gönderimde otomatik geçerli olur (app restart gerekmez) |
| DataProtection key persistence | Anahtar halkası App_Data/dp-keys/ klasörüne kalıcı yazılır — restart sonrası eski mail tokenları geçerli kalır |
| Token TTL | ExamSurvey = 30 gün, OptOut = 90 gün — sınırsız replay yüzeyi kapatıldı |
| HTML encoding | {AdSoyad} ve {BrandName} WebUtility.HtmlEncode ile yazılır — XSS vektörü kapatıldı |
| MailTemplateRenderer | Tek-pass regex (recursive substitution kapatıldı) |
| NL timezone | Tüm mail job'ları Hollanda lokal saatini esas alır (tutarlılık) |
| Inactive job query | Memory roundtrip kaldırıldı, tek EXISTS sorgusuna çevrildi |
| Yeni kullanıcı spam koruması | Hiç login olmamış + 2 günden yeni kayıtlara hatırlatma maili gönderilmez |
7.2 Kritik Güvenlik Garantileri
- CSRF — Tüm admin POST'larında
ValidateAntiForgeryToken - Token bütünlüğü — ASP.NET DataProtection HMAC ile imzalı, manipüle edilemez
- Token kullanım amacı ayrı — ExamSurvey ve CourseReminderOptOut farklı Protector purpose'u, cross-use imkânsız
- Idempotent landing'ler — Mail linkleri kaç kez tıklanırsa tıklansın yalnızca ilk tıklama DB'ye yazar
- Admin yetkilendirme —
AdminBaseControllerüzerinden[Authorize(Roles="Admin")] - Hangfire dashboard —
HollandHangfireAuthFilterile yalnızca Admin erişebilir - SQL injection — EF Core parametre tabanlı sorgular, string concat yok
- Iyzico 3D Secure — Tüm kart ödemeleri 3DS ile korunuyor
- Şifre koruma — PBKDF2, kişisel bilgi HTTPS, GDPR uyumlu opt-out
7.3 CSP (Content Security Policy)
SecurityHeadersMiddleware ile production'da whitelist edilmiş kaynaklar: Google Fonts, GTM/GA, Iyzico ödeme sayfası, Tabler CDN, Facebook pixel. Diğer her şey engellenir.
8 · Veritabanı Şeması
Bu son sprint'te eklenen yapılar — kullanıcı izleme, soru-modül-kurs many-to-many ilişkileri.
8.1 AspNetUsers Yeni Kolonlar
| Kolon | Tip | Amaç |
|---|---|---|
SinavTarihi | date nullable | Opsiyonel CBR sınav tarihi |
SinavAnketGonderildiAt | timestamptz | 3 gün sonra anket maili gönderim damgası |
SinavHatirlatmaGonderildiAt | timestamptz | 1 gün önce hatırlatma maili gönderim damgası |
KursHatirlatmaKapali | boolean | Opt-out flag |
KursHatirlatmaSonGonderim | timestamptz | 2 günde bir gönderim için son damga |
8.2 Yeni Many-to-Many Join Tabloları
| Tablo | İlişki |
|---|---|
QuestionModules | Question ⇄ Module (bir soru birden fazla modülde, ortak sorular) |
QuestionCourses | Question ⇄ Course (kurs havuzu — modülden bağımsız) |
8.3 Paket & Ödeme Yeni Kolonları YENİ
| Tablo / Kolon | Tip | Amaç |
|---|---|---|
Packages.Ozellikler | text nullable | Anasayfa paket kartı bullet listesi (satır satır) |
Payments.UpgradeFromSubscriptionId | bigint nullable | Yükseltme ödemesi ise yükseltilen eski aboneliğin Id'si |
8.4 Migration Zinciri
UserExamDate— SinavTarihi + SinavAnketGonderildiAtSinavHatirlatma— SinavHatirlatmaGonderildiAtKursHatirlatma— KursHatirlatmaKapali + KursHatirlatmaSonGonderimQuestionModuleManyToMany— eski Question.ModuleId verilerini koruyarak join tablosuna taşırQuestionCourseManyToMany— yeni QuestionCourses join tablosuPackageOzelliklerYENİ — Package.Ozellikler text alanıPaymentUpgradeYENİ — Payment.UpgradeFromSubscriptionIdUpgradeFromSubscriptionIdLongYENİ — int→long düzeltme
9 · Mimari Özet
Kullandığımız teknolojiler ve nasıl konuştukları.
┌────────────────────────┐
│ Client (Tailwind+JS) │
└──────────┬─────────────┘
│ HTTPS
┌──────────▼──────────────────────────────────────┐
│ ASP.NET Core 8 MVC │
│ - Public Area (Home, Account, Bildirim, Sinav) │
│ - Student Area (Hesabim, Course, Quiz) │
│ - Admin Area (Tabler UI, CRUD, Settings) │
│ - Middleware: CSP, RateLimit, Forwarded, Comp. │
└──────────┬───────────┬────────────┬─────────────┘
│ │ │
┌───────▼─────┐ ┌───▼────────┐ ┌─▼──────────┐
│ PostgreSQL │ │ Hangfire │ │ Iyzico │
│ (17 + EF8) │ │ (Postgres) │ │ Paraşüt │
└─────────────┘ └──────┬─────┘ └────────────┘
│
┌───────────┼──────────────┐
│ │ │
ExamSurvey ExamReminder InactiveUser
(12:00) (12:00) (18:00)
Hollanda lokal saat (DST-aware)
Anahtar Servisler
- StudentProgressService — modül başarı takibi, simülasyon algoritması, weighted sampling
- SettingsService — DB tabanlı dinamik config (admin'den canlı düzenlenebilir)
- MailTemplateRenderer — placeholder ikamesi (XSS-safe, tek-pass regex)
- NlTime — Europe/Amsterdam DST-aware cron yardımcısı
- PromotionService — sadakat ve sınav indirimleri
- OdemeService — Iyzico 3DS + Paraşüt fatura akışı
Otomatik İş Yükü (Hangfire Recurring Jobs)
| Job | Cron (NL local) | Açıklama |
|---|---|---|
| subscription-expiry-check | 03:00 | Süresi dolan abonelikleri Expired'a çevirir |
| exam-reminder-mailer | 12:00 | Sınavdan 1 gün önce hatırlatma |
| exam-survey-mailer | 12:00 | Sınavdan 3 gün sonra sonuç anketi |
| inactive-user-reminder | 18:00 | 2 gündür inaktif aboneye hatırlatma |
10 · Teklif & Fiyatlandırma
Yazılım kapsamı, müşteri-sorumluluğunda olan altyapı, fiyatlandırma ve destek modeli.
10.1 Kapsam
- Tüm yazılım (kaynak kodu ile) — bu dokümanda anlatılan tüm özellikler
- Sunucuya kurulum ve canlıya alma
- 1 (bir) gün online eğitim
- Iyzico ve Paraşüt entegrasyon ayarlarının kurulumu
- İlk SSL + domain bağlama desteği
- Sunucu / VPS / Hosting (öneri: Linux + .NET 8 + 4 GB RAM)
- PostgreSQL veritabanı hizmeti
- Domain adı ve DNS yönetimi
- Iyzico ve Paraşüt ticari hesapları (API anahtarları)
- SMTP servis aboneliği (mail gönderimi)
- Vimeo Standard aboneliği (≈ 563 TL x 12ay yıllık · video hosting) — detay
10.2 Fiyatlandırma
10.3 Yıllık Yenileme / Destek Paketi (1.000 €/yıl) — Neleri İçerir?
- Hata düzeltmeleri (bug fix)
- Teknik soru-cevap (WhatsApp / e-posta üzerinden)
- Küçük ayar ve güncellemeler (logo, metin, paket fiyatı yapısı, vb.)
- Güvenlik yamaları + .NET ve paket sürüm yükseltmeleri
- İhtiyaç doğrultusunda yıllık 1 oturum mini eğitim
10.4 Özel Ek Geliştirme (200 €/saat) — Nasıl Çalışır?
- Talep yazılı alınır (WhatsApp / e-posta)
- Maksimum 8 saat içinde projelendirme yapılır ve net teslim süresi bildirilir
- Müşteri onayından sonra geliştirmeye başlanır
- Saat bazında faturalandırılır
10.5 Ödeme Koşulları
| Kalem | Koşul |
|---|---|
| İlk Kurulum bedeli (4.000 €) | %50 başlangıçta · %50 canlıya alma sonrası |
| Yıllık Yenileme / Destek (1.000 €/yıl) | Yıllık peşin — her yılbaşında fatura |
| Özel Ek Geliştirme (200 €/saat) | Teslimde peşin — proje tamamlanıp test edildikten sonra |
10.6 USDT Cüzdan Adresi (TRC-20)
— Cüzdan adresi onay sonrası ileti̇lecek —
10.7 Anlık EUR ↔ USDT Hesaplama
Herhangi bir tutarı yaz, anlık kur ile karşılığını gör:
11 · Müşteri Kabul Listesi
Gözle doğrulayabileceğin maddeler — tek tek check edebilirsin.
- Anasayfada "Akıllı Öğrenme" bölümü görünüyor mu?
- Kayıt formunda Sınav Tarihi alanı (opsiyonel) var mı?
- Login sonrası admin → /Admin, öğrenci → /Student yönlendirmesi çalışıyor mu?
- Admin Dashboard'da 4+4 KPI kartı + 12 aylık ciro grafiği görünüyor mu?
- Admin → Kullanıcılar sayfasında Tümü/Aktif/Pasif sekmeleri çalışıyor mu?
- Admin → Ayarlar → Mail Şablonları sayfası 3 mail şablonu düzenleyebiliyor mu?
- Admin → Ayarlar → Anasayfa Metinleri → Yöntem Bölümü editörü açılıyor mu?
- Soru bankasında bir soru birden fazla modüle atanabiliyor mu?
- Soru bankasında bir soru kurs havuzuna atanabiliyor mu?
- Soru listesinde checkbox ile çoklu seçim + Toplu Atama modal'ı çalışıyor mu?
- Bir kursa girince üstte gradient "50 Soruluk Sınav Simülasyonu" butonu var mı?
- Hesabım sayfasında Bildirim Tercihleri bölümü görünüyor mu?
/bildirim-kapat?token=bogusaçıldığında "geçersiz bağlantı" mesajı çıkıyor mu?- Test mail (örn. SMTP debug) → şablonlardaki HTML doğru render ediliyor mu?
- Admin → Paketler → Düzenle ekranında Özellik Listesi textarea'sı görünüyor mu?
- Anasayfa paket kartlarında her pakette farklı bullet listesi görünüyor mu?
- Paket
CourseIdset edildiğinde kullanıcı sadece o kursa erişebiliyor mu? - Aktif aboneliği olan kullanıcının Aboneliklerim sayfasında "Paketi Yükselt" butonu görünüyor mu?
- Yükselt sayfasında üst paketler için net fark fiyatı (gün hesabı yok) gösteriliyor mu?
- Yükselt ödeme akışı Iyzico'ya yönleniyor ve sonunda eski abonelik iptal + yeni abonelik tam süre başlıyor mu?