feat(billing): payment infrastructure pre-prep

db: add plan, planExpiresAt, planProvider to tenant_settings (Appwrite MCP)

- schema.ts: TenantPlan type, TenantSettings plan fields
- subscription-types.ts: Emlak plan catalog (Free / Pro 499₺/ay)
- plan-limits.ts: resource limits (properties/customers/members/presentations)
  + getPlanUsage, requirePlanCapacity, PlanLimitError helpers
- subscription-actions.ts: startCheckoutAction (Polar→Shopier→mock fallback),
  activatePlanInDb / deactivatePlanInDb for webhook handlers,
  downgradeToFreeAction, getCurrentPlanAction
- /api/payments/polar/callback: verify webhook → activatePlanInDb on order/subscription events
- /api/payments/shopier/callback: verify HMAC → activate on fulfilled+paid (tenant
  email-matching TODO pending Shopier metadata support)
- /settings/billing: CurrentPlanCard with usage progress bars + UpgradeSection
- sidebar: Plan & Faturalama nav item
- PlanLimitDialog: Emlak-specific feature list
This commit is contained in:
egecankomur
2026-05-08 15:26:18 +03:00
parent 95a7cbaf0d
commit 3cce632eb3
11 changed files with 633 additions and 4 deletions
+5
View File
@@ -103,6 +103,11 @@ const navGroups = [
url: "/settings/account",
icon: FileText,
},
{
title: "Plan & Faturalama",
url: "/settings/billing",
icon: CreditCard,
},
],
},
];
+2 -2
View File
@@ -35,9 +35,9 @@ export function PlanLimitDialog({ open, onOpenChange, message }: Props) {
<div className="rounded-md border bg-muted/30 p-3 text-sm space-y-1">
<div className="font-medium text-foreground">Pro plan ile gelen avantajlar</div>
<ul className="text-muted-foreground space-y-0.5 list-disc list-inside">
<li>Sınırsız müşteri, finans kaydı, yazılım</li>
<li>Sınırsız ilan, müşteri ve sunum</li>
<li>Sınırsız ekip üyesi</li>
<li>Audit log + öncelikli destek</li>
<li>Yatırımcı portalı + öncelikli destek</li>
</ul>
</div>
<DialogFooter>