Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Stripe gerçeği: 3 abonelik past_due (3×₺999 = brüt MRR'ın ~%27'si), 1 abonelik dün dunning'den iptal (tugem, ₺999 kayıp); kurtarma tarihsel %0. Kök nedenler: (1) dunning e-postasının CTA'sı ödeme imkânı olmayan /dashboard/subscription'a gidiyordu, (2) kart güncelleme yüzeyi hiç yok + yeniden checkout 'Zaten aktif aboneliğiniz var' ile bloklu, (3) app past_due'yu hiç bilmiyordu (DB state yok, banner yok), (4) subscription.deleted no-op'tu (churn görünmez + status active kaldığı için re-subscribe kalıcı bloklu). - migration 0035: user_subscriptions.dunning_since + dunning_invoice_url - handleInvoiceFailed: dunning state persist + e-posta CTA'sı Stripe hosted invoice sayfasına (öde/yeni kart/3DS) + milestone e-posta (1./3./final — deneme başına aynı mail spam'i bitti) + attempt_count PostHog'a - handleInvoicePaid: her iki dalda dunning temizliği - handleSubscriptionDeleted: status→cancelled (re-subscribe deblke), subscription_churned PostHog event'i (reason: payment_failure/cancelled) - web: DunningBanner (kapatılamaz, kırmızı; CTA hosted invoice) dashboard'da - spec: yeni davranışa güncellendi + milestone/final testleri (14/14) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
10 lines
662 B
SQL
10 lines
662 B
SQL
-- Dunning görünürlüğü: yenileme tahsilatı patlayınca (invoice.payment_failed)
|
||
-- damgalanır, fatura ödenince (invoice.paid) veya abonelik kesin iptal olunca
|
||
-- temizlenir. dunning_invoice_url = Stripe hosted fatura sayfası — kullanıcının
|
||
-- açık faturayı ödeyebileceği/yeni kart girebileceği TEK self-serve yüzey
|
||
-- (uygulamada kart-güncelleme yok; %0 dunning kurtarmanın kök nedeni buydu).
|
||
-- IF NOT EXISTS → idempotent.
|
||
ALTER TABLE "user_subscriptions" ADD COLUMN IF NOT EXISTS "dunning_since" timestamp with time zone;
|
||
--> statement-breakpoint
|
||
ALTER TABLE "user_subscriptions" ADD COLUMN IF NOT EXISTS "dunning_invoice_url" text;
|