// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init generator client { provider = "prisma-client" output = "../src/lib/generated/prisma" } datasource db { provider = "postgresql" } model User { id String @id name String email String emailVerified Boolean @default(false) image String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt roleId Int? role UserRole? @relation(fields: [roleId], references: [id]) sessions Session[] accounts Account[] profiles Profile[] licenseKeys LicenseKey[] userProclamations UserProclamations[] @@unique([email]) @@map("user") } // I chose to create a Profile table here because honestly, I didn't want to waste // a bunch of time trying to figure out how to customize the default Better-Auth model. model Profile { id String @id @default(uuid()) userId String? user User? @relation(fields: [userId], references: [id], onDelete: Cascade) email String? firstName String lastName String phoneNumber String ghlContactId String? @map("ghl_contact_id") addresses Address[] @@index([userId]) @@index([email]) } model Address { id String @id @default(uuid()) profileId String profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade) street String city String state String postalCode String country String type String @default("Mailing") isDefaultMailing Boolean @default(false) isDefaultBilling Boolean @default(false) isDefaultShipping Boolean @default(false) } model Session { id String @id expiresAt DateTime token String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt ipAddress String? userAgent String? userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([token]) @@index([userId]) @@map("session") } model Account { id String @id accountId String providerId String userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) accessToken String? refreshToken String? idToken String? accessTokenExpiresAt DateTime? refreshTokenExpiresAt DateTime? scope String? password String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([userId]) @@map("account") } model UserRole { id Int @id @default(autoincrement()) name String users User[] } model Verification { id String @id identifier String value String expiresAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([identifier]) @@map("verification") } model Proclamation { id String @id @default(uuid()) name String @unique content String solfeggioFrequencyId Int solfeggioFrequency SolfeggioFrequency @relation(fields: [solfeggioFrequencyId], references: [id]) categoryId Int category ProclamationCategory @relation(fields: [categoryId], references: [id]) groupId Int group ProclamationGroup @relation(fields: [groupId], references: [id]) userProclamations UserProclamations[] } model ProclamationGroup { id Int @id @default(autoincrement()) name String @unique sortOrder Int @default(0) proclamations Proclamation[] } model UserProclamations { userId String user User @relation(fields: [userId], references: [id]) proclamationId String proclamation Proclamation @relation(fields: [proclamationId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, proclamationId]) } model SolfeggioFrequency { id Int @id @default(autoincrement()) name String @unique value Int @unique proclamations Proclamation[] } model ProclamationCategory { id Int @id @default(autoincrement()) name String @unique sortOrder Int @default(0) proclamations Proclamation[] } // Archive of the former child sub-categories removed when the // ProclamationCategory hierarchy was flattened. Kept for recovery/audit. // `@@ignore` keeps it out of the generated client while Prisma remains aware // of the table so `migrate dev` does not report it as an untracked table. model ProclamationCategoryLegacy { id Int @id name String parentId Int? sortOrder Int @default(0) @@map("ProclamationCategoryLegacy") @@ignore } // Archive of the category->subscription-level mappings for the child // categories removed when the category hierarchy was flattened. Kept with // `@@ignore` so Prisma remains aware of the table but it is excluded from the // generated client and Prisma's own migrations. model ProclamationCategorySubscriptionLevelLegacy { categoryId Int subscriptionLevelId Int @@id([categoryId, subscriptionLevelId]) @@map("ProclamationCategorySubscriptionLevelLegacy") @@ignore } model LicenseKey { id String @id @default(uuid()) key String @unique active Boolean userId String? user User? @relation(fields: [userId], references: [id], onDelete: SetNull) email String? @@index([userId]) @@index([email]) } model ApiKey { id String @id @default(cuid()) keyPrefix String keyHash String @unique createdAt DateTime @default(now()) expiresAt DateTime? revokedAt DateTime? } // Portal-editable 7-color palette per canonical solfeggio frequency id (1-9). // `solfeggioFrequencyId` is the canonical id the kiosk uses (see // v2-serializers.ts), not the DB autoincrement id of `SolfeggioFrequency`. model ColorPalette { solfeggioFrequencyId Int @id colors Json // ["#RRGGBB", ... x7] @@map("ColorPalette") }