feat(billing): integrate Stripe for subscription management and billing access

- Added billing-related fields to the User model in the database.
- Implemented functions for managing billing access, including trial periods and subscription statuses.
- Created new billing utility functions for Stripe integration.
- Updated onboarding page to include billing overview and workspace creation eligibility.
- Enhanced route access checks to require billing access for certain actions.
- Implemented cleanup scripts for expired billing workspaces and associated media.
- Updated header component to conditionally show app navigation based on billing access.
- Added new migrations for billing-related database changes.
This commit is contained in:
Yusuf İpek
2026-04-08 17:50:40 +03:00
parent 8db7a031e6
commit 6f22b0bf8b
45 changed files with 1859 additions and 218 deletions
@@ -0,0 +1,20 @@
CREATE TYPE "BillingSubscriptionStatus" AS ENUM (
'FREE',
'TRIALING',
'ACTIVE',
'PAST_DUE',
'CANCELED',
'UNPAID',
'INCOMPLETE',
'INCOMPLETE_EXPIRED'
);
ALTER TABLE "users"
ADD COLUMN "stripeCustomerId" TEXT,
ADD COLUMN "stripeSubscriptionId" TEXT,
ADD COLUMN "stripePriceId" TEXT,
ADD COLUMN "stripeCurrentPeriodEnd" TIMESTAMP(3),
ADD COLUMN "subscriptionStatus" "BillingSubscriptionStatus" NOT NULL DEFAULT 'FREE';
CREATE UNIQUE INDEX "users_stripeCustomerId_key" ON "users"("stripeCustomerId");
CREATE UNIQUE INDEX "users_stripeSubscriptionId_key" ON "users"("stripeSubscriptionId");
@@ -0,0 +1,7 @@
ALTER TABLE "users"
ADD COLUMN "trialEndsAt" TIMESTAMP(3),
ADD COLUMN "billingAccessEndedAt" TIMESTAMP(3);
UPDATE "users"
SET "trialEndsAt" = "createdAt" + INTERVAL '7 days'
WHERE "trialEndsAt" IS NULL;
@@ -0,0 +1,3 @@
ALTER TABLE "users"
ADD COLUMN "stripeCancelAtPeriodEnd" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "stripeCancelAt" TIMESTAMP(3);
@@ -0,0 +1,6 @@
ALTER TABLE "users"
ADD COLUMN "billingTrialConsumedAt" TIMESTAMP(3);
UPDATE "users"
SET "billingTrialConsumedAt" = "trialEndsAt"
WHERE "trialEndsAt" IS NOT NULL;
+21
View File
@@ -22,6 +22,16 @@ model User {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
onboardingCompletedAt DateTime?
trialEndsAt DateTime?
billingTrialConsumedAt DateTime?
stripeCustomerId String? @unique
stripeSubscriptionId String? @unique
stripePriceId String?
stripeCurrentPeriodEnd DateTime?
stripeCancelAtPeriodEnd Boolean @default(false)
stripeCancelAt DateTime?
billingAccessEndedAt DateTime?
subscriptionStatus BillingSubscriptionStatus @default(FREE)
// Relations
accounts Account[]
@@ -44,6 +54,17 @@ model User {
@@map("users")
}
enum BillingSubscriptionStatus {
FREE
TRIALING
ACTIVE
PAST_DUE
CANCELED
UNPAID
INCOMPLETE
INCOMPLETE_EXPIRED
}
enum FeedbackEntryType {
FEEDBACK
REVIEW