feat(billing): indirim kodu sistemi (admin panel + Stripe promo + ödeme)
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Admin paneli (admin@sase.tr) kod üretir/takip eder, ödeme sayfası kodu uygular. Kodlar Stripe Coupon + Promotion Code olarak yaşar (limit/süre/ kullanım Stripe redemption'da enforce edilir); yerel discount_codes aynası panel listeleme + checkout-anı preview içindir. - migration 0022_discount_codes + schema (discount_codes) - DiscountCodesModule: admin CRUD (@Roles admin) + /discount-codes/validate (login) - StripeService: createPromotion / deactivatePromotion / getPromotionRedemptions / previewDiscount + resolvePlanAmount; createCheckoutSession opsiyonel discountCode -> discounts[{promotion_code}] + metadata.discount_code; webhook gerçek tahsilatı (session.amount_total) yazar + ayna times_redeemed++ - web: /dashboard/admin/discount-codes paneli + ödeme adımı indirim alanı (validate preview -> indirimli özet -> kod checkout'a); tr/en çeviriler - 7 birim test (previewDiscount: % / sabit / süre / geçersiz/pasif/dolu/limit) Not: 2026-04-22 Stripe API promotionCodes.create `promotion:{type:'coupon'}` kullanıyor (üst-seviye `coupon` değil). dev'de Stripe key yok -> CREATE dev'de 503; E2E için dev'e Stripe TEST key gerekir. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,7 @@ import { Route as DashboardOemCodeRouteImport } from './routes/dashboard/oem.$co
|
||||
import { Route as DashboardBlogSlugRouteImport } from './routes/dashboard/blog_/$slug'
|
||||
import { Route as DashboardAdminUsersRouteImport } from './routes/dashboard/admin/users'
|
||||
import { Route as DashboardAdminReferralsRouteImport } from './routes/dashboard/admin/referrals'
|
||||
import { Route as DashboardAdminDiscountCodesRouteImport } from './routes/dashboard/admin/discount-codes'
|
||||
import { Route as DashboardAdminCopyLogsRouteImport } from './routes/dashboard/admin/copy-logs'
|
||||
import { Route as DashboardAdminAnalyticsRouteImport } from './routes/dashboard/admin/analytics'
|
||||
import { Route as DashboardVehiclesIdIndexRouteImport } from './routes/dashboard/vehicles_/$id/index'
|
||||
@@ -229,6 +230,12 @@ const DashboardAdminReferralsRoute = DashboardAdminReferralsRouteImport.update({
|
||||
path: '/admin/referrals',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardAdminDiscountCodesRoute =
|
||||
DashboardAdminDiscountCodesRouteImport.update({
|
||||
id: '/admin/discount-codes',
|
||||
path: '/admin/discount-codes',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardAdminCopyLogsRoute = DashboardAdminCopyLogsRouteImport.update({
|
||||
id: '/admin/copy-logs',
|
||||
path: '/admin/copy-logs',
|
||||
@@ -340,6 +347,7 @@ export interface FileRoutesByFullPath {
|
||||
'/dashboard/': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
'/dashboard/admin/discount-codes': typeof DashboardAdminDiscountCodesRoute
|
||||
'/dashboard/admin/referrals': typeof DashboardAdminReferralsRoute
|
||||
'/dashboard/admin/users': typeof DashboardAdminUsersRoute
|
||||
'/dashboard/blog/$slug': typeof DashboardBlogSlugRoute
|
||||
@@ -388,6 +396,7 @@ export interface FileRoutesByTo {
|
||||
'/dashboard': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
'/dashboard/admin/discount-codes': typeof DashboardAdminDiscountCodesRoute
|
||||
'/dashboard/admin/referrals': typeof DashboardAdminReferralsRoute
|
||||
'/dashboard/admin/users': typeof DashboardAdminUsersRoute
|
||||
'/dashboard/blog/$slug': typeof DashboardBlogSlugRoute
|
||||
@@ -439,6 +448,7 @@ export interface FileRoutesById {
|
||||
'/dashboard/': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
'/dashboard/admin/discount-codes': typeof DashboardAdminDiscountCodesRoute
|
||||
'/dashboard/admin/referrals': typeof DashboardAdminReferralsRoute
|
||||
'/dashboard/admin/users': typeof DashboardAdminUsersRoute
|
||||
'/dashboard/blog_/$slug': typeof DashboardBlogSlugRoute
|
||||
@@ -490,6 +500,7 @@ export interface FileRouteTypes {
|
||||
| '/dashboard/'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
| '/dashboard/admin/discount-codes'
|
||||
| '/dashboard/admin/referrals'
|
||||
| '/dashboard/admin/users'
|
||||
| '/dashboard/blog/$slug'
|
||||
@@ -538,6 +549,7 @@ export interface FileRouteTypes {
|
||||
| '/dashboard'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
| '/dashboard/admin/discount-codes'
|
||||
| '/dashboard/admin/referrals'
|
||||
| '/dashboard/admin/users'
|
||||
| '/dashboard/blog/$slug'
|
||||
@@ -588,6 +600,7 @@ export interface FileRouteTypes {
|
||||
| '/dashboard/'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
| '/dashboard/admin/discount-codes'
|
||||
| '/dashboard/admin/referrals'
|
||||
| '/dashboard/admin/users'
|
||||
| '/dashboard/blog_/$slug'
|
||||
@@ -866,6 +879,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DashboardAdminReferralsRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/admin/discount-codes': {
|
||||
id: '/dashboard/admin/discount-codes'
|
||||
path: '/admin/discount-codes'
|
||||
fullPath: '/dashboard/admin/discount-codes'
|
||||
preLoaderRoute: typeof DashboardAdminDiscountCodesRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/admin/copy-logs': {
|
||||
id: '/dashboard/admin/copy-logs'
|
||||
path: '/admin/copy-logs'
|
||||
@@ -997,6 +1017,7 @@ interface DashboardRouteChildren {
|
||||
DashboardIndexRoute: typeof DashboardIndexRoute
|
||||
DashboardAdminAnalyticsRoute: typeof DashboardAdminAnalyticsRoute
|
||||
DashboardAdminCopyLogsRoute: typeof DashboardAdminCopyLogsRoute
|
||||
DashboardAdminDiscountCodesRoute: typeof DashboardAdminDiscountCodesRoute
|
||||
DashboardAdminReferralsRoute: typeof DashboardAdminReferralsRoute
|
||||
DashboardAdminUsersRoute: typeof DashboardAdminUsersRoute
|
||||
DashboardBlogSlugRoute: typeof DashboardBlogSlugRoute
|
||||
@@ -1030,6 +1051,7 @@ const DashboardRouteChildren: DashboardRouteChildren = {
|
||||
DashboardIndexRoute: DashboardIndexRoute,
|
||||
DashboardAdminAnalyticsRoute: DashboardAdminAnalyticsRoute,
|
||||
DashboardAdminCopyLogsRoute: DashboardAdminCopyLogsRoute,
|
||||
DashboardAdminDiscountCodesRoute: DashboardAdminDiscountCodesRoute,
|
||||
DashboardAdminReferralsRoute: DashboardAdminReferralsRoute,
|
||||
DashboardAdminUsersRoute: DashboardAdminUsersRoute,
|
||||
DashboardBlogSlugRoute: DashboardBlogSlugRoute,
|
||||
|
||||
Reference in New Issue
Block a user