feat: Implement Stripe integration for subscription management, including new services, controllers, Prisma models, and webhook handling.

This commit is contained in:
pradeepkumar
2026-03-07 10:09:50 +05:30
parent b3f43bf2e5
commit d1e4e12510
13 changed files with 860 additions and 9 deletions

View File

@@ -80,6 +80,15 @@ enum SupportChatStatus {
CLOSED
}
enum SubscriptionStatus {
ACTIVE
PAST_DUE
CANCELED
UNPAID
TRIALING
INCOMPLETE
}
// ===========================================
// USER - Authentication Only
@@ -143,6 +152,10 @@ model User {
// Support Chat
supportChats SupportChat[]
// Subscriptions & Payments
subscriptions AgentSubscription[]
payments Payment[]
@@index([email])
@@index([role])
@@index([status])
@@ -231,6 +244,9 @@ model AgentProfile {
isFeatured Boolean @default(false)
isAvailable Boolean @default(true) // Agent availability status for connect requests
// Subscription (denormalized for quick access)
subscriptionStatus String? // "ACTIVE", "NONE", etc.
// Stats (denormalized for performance)
totalReviews Int @default(0)
averageRating Float @default(0)
@@ -617,3 +633,72 @@ model SupportMessage {
@@index([chatId])
@@map("support_messages")
}
// ===========================================
// SUBSCRIPTION & PAYMENTS
// ===========================================
model SubscriptionPlan {
id String @id @default(uuid())
name String // "Professional Annual"
description String? @db.Text
stripePriceId String @unique // Stripe Price ID (price_xxx)
amount Int // Amount in cents (49900)
currency String @default("usd")
interval String @default("year") // "month" | "year"
features Json? // ["Feature 1", "Feature 2"]
isActive Boolean @default(true)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
subscriptions AgentSubscription[]
@@index([isActive])
@@map("subscription_plans")
}
model AgentSubscription {
id String @id @default(uuid())
userId String
planId String
stripeCustomerId String // cus_xxx
stripeSubscriptionId String? @unique // sub_xxx
status SubscriptionStatus @default(INCOMPLETE)
currentPeriodStart DateTime?
currentPeriodEnd DateTime?
cancelAtPeriodEnd Boolean @default(false)
canceledAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
plan SubscriptionPlan @relation(fields: [planId], references: [id])
payments Payment[]
@@index([userId])
@@index([status])
@@index([stripeCustomerId])
@@map("agent_subscriptions")
}
model Payment {
id String @id @default(uuid())
subscriptionId String?
userId String
stripePaymentIntentId String? @unique // pi_xxx
stripeInvoiceId String? @unique // in_xxx
amount Int // cents
currency String @default("usd")
status String // "succeeded", "failed", "pending"
receiptUrl String?
createdAt DateTime @default(now())
subscription AgentSubscription? @relation(fields: [subscriptionId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([subscriptionId])
@@index([status])
@@map("payments")
}