generator client { provider = "prisma-client-js" previewFeatures = ["typedSql"] output = "./client" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Organization { id String @id @default(uuid()) name String description String? UserOrganizations UserOrganization[] Lists List[] Subscribers Subscriber[] Templates Template[] Campaigns Campaign[] SmtpSettings SmtpSettings[] ApiKeys ApiKey[] GeneralSettings GeneralSettings? EmailDeliverySettings EmailDeliverySettings? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model User { id String @id @default(uuid()) name String email String @unique password String pwdVersion Int @default(1) UserOrganizations UserOrganization[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model UserOrganization { userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) @@id([userId, organizationId]) } model Subscriber { id String @id @default(uuid()) name String? email String organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) ListSubscribers ListSubscriber[] Messages Message[] Clicks Click[] Metadata SubscriberMetadata[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt emailVerified Boolean @default(false) emailVerificationToken String? @unique emailVerificationTokenExpiresAt DateTime? @@unique([organizationId, email]) @@index([createdAt, id]) } model SubscriberMetadata { id String @id @default(uuid()) key String value String subscriberId String Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([subscriberId, key]) } enum CampaignStatus { DRAFT SCHEDULED CREATING SENDING COMPLETED CANCELLED } model Campaign { id String @id @default(uuid()) title String description String? subject String? content String? completedAt DateTime? status CampaignStatus @default(DRAFT) scheduledAt DateTime? htmlOnly Boolean @default(false) openTracking Boolean @default(true) unsubscribedCount Int @default(0) organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) templateId String? Template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull) Messages Message[] CampaignLists CampaignList[] TrackedLinks TrackedLink[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model List { id String @id @default(uuid()) name String description String? organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) ListSubscribers ListSubscriber[] CampaignLists CampaignList[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model CampaignList { campaignId String listId String Campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade) List List @relation(fields: [listId], references: [id], onDelete: Cascade) @@id([campaignId, listId]) } model ListSubscriber { id String @id @default(uuid()) unsubscribedAt DateTime? listId String subscriberId String List List @relation(fields: [listId], references: [id], onDelete: Cascade) Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([listId, subscriberId]) } model Template { id String @id @default(uuid()) name String description String? content String organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) Campaigns Campaign[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } enum MessageStatus { QUEUED PENDING SENT OPENED CLICKED FAILED RETRYING CANCELLED } model Message { id String @id @default(uuid()) content String? status MessageStatus @default(QUEUED) sentAt DateTime? tries Int @default(0) lastTriedAt DateTime? /// Returned from SMTP response messageId String? subscriberId String Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade) campaignId String Campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade) error String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([updatedAt, id]) } model TrackedLink { id String @id @default(uuid()) url String campaignId String? Campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: SetNull) Clicks Click[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([url, campaignId]) } model Click { id String @id @default(uuid()) trackedLinkId String? TrackedLink TrackedLink? @relation(fields: [trackedLinkId], references: [id], onDelete: Cascade) subscriberId String? Subscriber Subscriber? @relation(fields: [subscriberId], references: [id], onDelete: SetNull) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } enum SmtpEncryption { STARTTLS SSL_TLS NONE } model ApiKey { id String @id @default(uuid()) name String key String @unique lastUsed DateTime? expiresAt DateTime? organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model SmtpSettings { id String @id @default(uuid()) host String port Int username String password String fromEmail String? fromName String? secure Boolean @default(true) encryption SmtpEncryption @default(STARTTLS) timeout Int @default(30000) organizationId String Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model GeneralSettings { id String @id @default(uuid()) defaultFromEmail String? defaultFromName String? baseURL String? cleanupInterval Int @default(90) organizationId String @unique Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model EmailDeliverySettings { id String @id @default(uuid()) rateLimit Int @default(100) rateWindow Int @default(3600) maxRetries Int @default(3) retryDelay Int @default(300) concurrency Int @default(5) connectionTimeout Int @default(30000) organizationId String @unique Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }