cal/packages/prisma/schema.prisma
sean-brydon aab5ee344c
feat: Org settings - profile,appearance, child teams, create new child (#9231)
* Initial commit

* Adding feature flag

* Desktop first banner, mobile pending

* Removing dead code and img

* AppInstallButtonBase

* WIP

* Adds Email verification template+translations for organizations (#9202)

* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)

* Change scopedMembers to orgMembers

* Change to orgUsers

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Session logic to show org label

* Step 2 done, avatar not working

* List orgs and list teams specific if orgs exist

* Conditionally show org - fix settings layout - add labels for all pages

* Profile Page + update

* Org specific team creation

* appearance page

* Ensure members cant of org cant update settings in UI

* Fix update handler imports

* hide billing on sub teams

* Update profile slug page

* Letting duplicate slugs for teams to support orgs

* Add slug coliisions for org

* Covering null on unique clauses

* Covering null on unique clauses

* Extract to utils

* Update settings to use subdomain path in team url , team + org

* Supporting having the orgId in the session cookie

* Onboarding admins step

* Last step to create teams

* Update handler comments

* Upgrade ORG banner - disabled team banner for child teams

* Handle publishing ORGS

* Fix licenese issue

* Update packages/trpc/server/routers/viewer/teams/create.handler.ts

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* A11ly

* Feedback

* Making an org avatar (temp)

* Add slug colission detection for user and team name

* Fix Import

* Remove update password func

* Fix module import over relative

* feat: organization event type filter (#9253)

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Missing changes to support orgs schema changes

* Remove app install button sa its in 9337

* Remove i18n key not being used

* feat: Onboarding process to create an organization (#9184)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Making sure we check requestedSlug now

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: [CAL-1816] Organization subdomain support (#9345)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* Covering users and subteams, excluding non-org users

* Unpublished teams shows correctly

* Create subdomain in Vercel

* feedback

* Renaming Vercel env vars

* Vercel domain check before creation

* Supporting cal-staging.com

* Change to have vercel detect it

* vercel domain check data message error

* Remove check domain

* Making sure we check requestedSlug now

* Feedback and unneeded code

* Reverting unneeded changes

* Unneeded changes

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Vercel subdomain creation in PROD only

* feat: organization settings general and members page (#9266)

* feat: organization settings general page

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* feat: add members page

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore: remove

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: use invalidate

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: delete mutation

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: remove organization id

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: use zod schema

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Type fixes

* Reverting changes

* Update UsernameTextfield.tsx

* More reverts

* Update next-auth-options.ts

* Update common.json

* Type fixes

* Include invite token for orgs

* Update org schema

* Make token settings optional as it isnt used in orgs yet

* Fix missing prop

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-06-15 10:27:39 -07:00

880 lines
27 KiB
Plaintext

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["views", "jsonProtocol"]
}
generator zod {
provider = "zod-prisma"
output = "./zod"
imports = "./zod-utils"
relationModel = "default"
}
generator enums {
provider = "ts-node --transpile-only ./enum-generator"
}
enum SchedulingType {
ROUND_ROBIN @map("roundRobin")
COLLECTIVE @map("collective")
MANAGED @map("managed")
}
enum PeriodType {
UNLIMITED @map("unlimited")
ROLLING @map("rolling")
RANGE @map("range")
}
model Host {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
eventTypeId Int
isFixed Boolean @default(false)
@@id([userId, eventTypeId])
@@index([userId])
@@index([eventTypeId])
}
model EventType {
id Int @id @default(autoincrement())
/// @zod.min(1)
title String
/// @zod.custom(imports.eventTypeSlug)
slug String
description String?
position Int @default(0)
/// @zod.custom(imports.eventTypeLocations)
locations Json?
length Int
offsetStart Int @default(0)
hidden Boolean @default(false)
hosts Host[]
users User[] @relation("user_eventtype")
owner User? @relation("owner", fields: [userId], references: [id], onDelete: Cascade)
userId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int?
hashedLink HashedLink?
bookings Booking[]
availability Availability[]
webhooks Webhook[]
destinationCalendar DestinationCalendar?
eventName String?
customInputs EventTypeCustomInput[]
parentId Int?
parent EventType? @relation("managed_eventtype", fields: [parentId], references: [id], onDelete: Cascade)
children EventType[] @relation("managed_eventtype")
/// @zod.custom(imports.eventTypeBookingFields)
bookingFields Json?
timeZone String?
periodType PeriodType @default(UNLIMITED)
periodStartDate DateTime?
periodEndDate DateTime?
periodDays Int?
periodCountCalendarDays Boolean?
requiresConfirmation Boolean @default(false)
/// @zod.custom(imports.recurringEventType)
recurringEvent Json?
disableGuests Boolean @default(false)
hideCalendarNotes Boolean @default(false)
/// @zod.min(0)
minimumBookingNotice Int @default(120)
beforeEventBuffer Int @default(0)
afterEventBuffer Int @default(0)
seatsPerTimeSlot Int?
seatsShowAttendees Boolean? @default(false)
schedulingType SchedulingType?
schedule Schedule? @relation(fields: [scheduleId], references: [id])
scheduleId Int?
// price is deprecated. It has now moved to metadata.apps.stripe.price. Plan to drop this column.
price Int @default(0)
// currency is deprecated. It has now moved to metadata.apps.stripe.currency. Plan to drop this column.
currency String @default("usd")
slotInterval Int?
/// @zod.custom(imports.EventTypeMetaDataSchema)
metadata Json?
/// @zod.custom(imports.successRedirectUrl)
successRedirectUrl String?
workflows WorkflowsOnEventTypes[]
/// @zod.custom(imports.intervalLimitsType)
bookingLimits Json?
/// @zod.custom(imports.intervalLimitsType)
durationLimits Json?
@@unique([userId, slug])
@@unique([teamId, slug])
@@unique([userId, parentId])
@@index([userId])
@@index([teamId])
}
model Credential {
id Int @id @default(autoincrement())
// @@type is deprecated
type String
key Json
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int?
app App? @relation(fields: [appId], references: [slug], onDelete: Cascade)
// How to make it a required column?
appId String?
destinationCalendars DestinationCalendar[]
invalid Boolean? @default(false)
@@index([userId])
@@index([appId])
}
enum IdentityProvider {
CAL
GOOGLE
SAML
}
model DestinationCalendar {
id Int @id @default(autoincrement())
integration String
externalId String
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int? @unique
booking Booking[]
eventType EventType? @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
eventTypeId Int? @unique
credentialId Int?
credential Credential? @relation(fields: [credentialId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([eventTypeId])
@@index([credentialId])
}
enum UserPermissionRole {
USER
ADMIN
}
model User {
id Int @id @default(autoincrement())
username String?
name String?
/// @zod.email()
email String
emailVerified DateTime?
password String?
bio String?
avatar String?
timeZone String @default("Europe/London")
weekStart String @default("Sunday")
// DEPRECATED - TO BE REMOVED
startTime Int @default(0)
endTime Int @default(1440)
// </DEPRECATED>
bufferTime Int @default(0)
hideBranding Boolean @default(false)
theme String?
createdDate DateTime @default(now()) @map(name: "created")
trialEndsAt DateTime?
eventTypes EventType[] @relation("user_eventtype")
credentials Credential[]
teams Membership[]
bookings Booking[]
schedules Schedule[]
defaultScheduleId Int?
selectedCalendars SelectedCalendar[]
completedOnboarding Boolean @default(false)
locale String?
timeFormat Int? @default(12)
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
identityProvider IdentityProvider @default(CAL)
identityProviderId String?
availability Availability[]
invitedTo Int?
webhooks Webhook[]
brandColor String @default("#292929")
darkBrandColor String @default("#fafafa")
// the location where the events will end up
destinationCalendar DestinationCalendar?
away Boolean @default(false)
// participate in dynamic group booking or not
allowDynamicBooking Boolean? @default(true)
/// @zod.custom(imports.userMetadata)
metadata Json?
verified Boolean? @default(false)
role UserPermissionRole @default(USER)
disableImpersonation Boolean @default(false)
impersonatedUsers Impersonations[] @relation("impersonated_user")
impersonatedBy Impersonations[] @relation("impersonated_by_user")
apiKeys ApiKey[]
accounts Account[]
sessions Session[]
Feedback Feedback[]
ownedEventTypes EventType[] @relation("owner")
workflows Workflow[]
routingForms App_RoutingForms_Form[] @relation("routing-form")
verifiedNumbers VerifiedNumber[]
hosts Host[]
organizationId Int?
organization Team? @relation("scope", fields: [organizationId], references: [id], onDelete: SetNull)
// Linking account code for orgs v2
//linkedByUserId Int?
//linkedBy User? @relation("linked_account", fields: [linkedByUserId], references: [id], onDelete: Cascade)
//linkedUsers User[] @relation("linked_account")*/
@@unique([email])
@@unique([email, username])
@@unique([username, organizationId])
@@index([emailVerified])
@@index([identityProvider])
@@index([identityProviderId])
@@map(name: "users")
}
model Team {
id Int @id @default(autoincrement())
/// @zod.min(1)
name String
/// @zod.min(1)
slug String?
logo String?
appLogo String?
appIconLogo String?
bio String?
hideBranding Boolean @default(false)
hideBookATeamMember Boolean @default(false)
members Membership[]
eventTypes EventType[]
workflows Workflow[]
createdAt DateTime @default(now())
/// @zod.custom(imports.teamMetadataSchema)
metadata Json?
theme String?
brandColor String @default("#292929")
darkBrandColor String @default("#fafafa")
verifiedNumbers VerifiedNumber[]
parentId Int?
parent Team? @relation("organization", fields: [parentId], references: [id], onDelete: Cascade)
children Team[] @relation("organization")
orgUsers User[] @relation("scope")
inviteToken VerificationToken?
webhooks Webhook[]
timeFormat Int?
timeZone String @default("Europe/London")
weekStart String @default("Sunday")
routingForms App_RoutingForms_Form[]
@@unique([slug, parentId])
}
enum MembershipRole {
MEMBER
ADMIN
OWNER
}
model Membership {
teamId Int
userId Int
accepted Boolean @default(false)
role MembershipRole
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
disableImpersonation Boolean @default(false)
@@id([userId, teamId])
@@index([teamId])
@@index([userId])
}
model VerificationToken {
id Int @id @default(autoincrement())
identifier String
token String @unique
expires DateTime
expiresInDays Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
teamId Int? @unique
team Team? @relation(fields: [teamId], references: [id])
@@unique([identifier, token])
@@index([token])
}
model BookingReference {
id Int @id @default(autoincrement())
/// @zod.min(1)
type String
/// @zod.min(1)
uid String
meetingId String?
meetingPassword String?
meetingUrl String?
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
bookingId Int?
externalCalendarId String?
deleted Boolean?
credentialId Int?
@@index([bookingId])
@@index([credentialId])
@@index([type])
@@index([uid])
}
model Attendee {
id Int @id @default(autoincrement())
email String
name String
timeZone String
locale String? @default("en")
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
bookingId Int?
bookingSeat BookingSeat?
@@index([email])
@@index([bookingId])
}
enum BookingStatus {
CANCELLED @map("cancelled")
ACCEPTED @map("accepted")
REJECTED @map("rejected")
PENDING @map("pending")
}
model Booking {
id Int @id @default(autoincrement())
uid String @unique
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int?
references BookingReference[]
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
title String
description String?
customInputs Json?
/// @zod.custom(imports.bookingResponses)
responses Json?
startTime DateTime
endTime DateTime
attendees Attendee[]
location String?
createdAt DateTime @default(now())
updatedAt DateTime?
status BookingStatus @default(ACCEPTED)
paid Boolean @default(false)
payment Payment[]
destinationCalendar DestinationCalendar? @relation(fields: [destinationCalendarId], references: [id])
destinationCalendarId Int?
cancellationReason String?
rejectionReason String?
dynamicEventSlugRef String?
dynamicGroupSlugRef String?
rescheduled Boolean?
fromReschedule String?
recurringEventId String?
smsReminderNumber String?
workflowReminders WorkflowReminder[]
scheduledJobs String[]
seatsReferences BookingSeat[]
/// @zod.custom(imports.bookingMetadataSchema)
metadata Json?
isRecorded Boolean @default(false)
@@index([eventTypeId])
@@index([userId])
@@index([destinationCalendarId])
@@index([recurringEventId])
@@index([uid])
@@index([status])
}
model Schedule {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
eventType EventType[]
name String
timeZone String?
availability Availability[]
@@index([userId])
}
model Availability {
id Int @id @default(autoincrement())
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int?
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
days Int[]
startTime DateTime @db.Time
endTime DateTime @db.Time
date DateTime? @db.Date
Schedule Schedule? @relation(fields: [scheduleId], references: [id])
scheduleId Int?
@@index([userId])
@@index([eventTypeId])
@@index([scheduleId])
}
model SelectedCalendar {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
integration String
externalId String
@@id([userId, integration, externalId])
@@index([userId])
@@index([integration])
@@index([externalId])
}
enum EventTypeCustomInputType {
TEXT @map("text")
TEXTLONG @map("textLong")
NUMBER @map("number")
BOOL @map("bool")
RADIO @map("radio")
PHONE @map("phone")
}
model EventTypeCustomInput {
id Int @id @default(autoincrement())
eventTypeId Int
eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
label String
type EventTypeCustomInputType
/// @zod.custom(imports.customInputOptionSchema)
options Json?
required Boolean
placeholder String @default("")
@@index([eventTypeId])
}
model ResetPasswordRequest {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String
expires DateTime
}
enum ReminderType {
PENDING_BOOKING_CONFIRMATION
}
model ReminderMail {
id Int @id @default(autoincrement())
referenceId Int
reminderType ReminderType
elapsedMinutes Int
createdAt DateTime @default(now())
@@index([referenceId])
@@index([reminderType])
}
model Payment {
id Int @id @default(autoincrement())
uid String @unique
app App? @relation(fields: [appId], references: [slug], onDelete: Cascade)
appId String?
bookingId Int
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
amount Int
fee Int
currency String
success Boolean
refunded Boolean
data Json
externalId String @unique
paymentOption PaymentOption? @default(ON_BOOKING)
@@index([bookingId])
@@index([externalId])
}
enum PaymentOption {
ON_BOOKING
HOLD
}
enum WebhookTriggerEvents {
BOOKING_CREATED
BOOKING_PAID
BOOKING_RESCHEDULED
BOOKING_REQUESTED
BOOKING_CANCELLED
BOOKING_REJECTED
FORM_SUBMITTED
MEETING_ENDED
RECORDING_READY
}
model Webhook {
id String @id @unique
userId Int?
teamId Int?
eventTypeId Int?
/// @zod.url()
subscriberUrl String
payloadTemplate String?
createdAt DateTime @default(now())
active Boolean @default(true)
eventTriggers WebhookTriggerEvents[]
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
eventType EventType? @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
app App? @relation(fields: [appId], references: [slug], onDelete: Cascade)
appId String?
secret String?
@@unique([userId, subscriberUrl], name: "courseIdentifier")
}
model Impersonations {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
impersonatedUser User @relation("impersonated_user", fields: [impersonatedUserId], references: [id], onDelete: Cascade)
impersonatedBy User @relation("impersonated_by_user", fields: [impersonatedById], references: [id], onDelete: Cascade)
impersonatedUserId Int
impersonatedById Int
}
model ApiKey {
id String @id @unique @default(cuid())
userId Int
note String?
createdAt DateTime @default(now())
expiresAt DateTime?
lastUsedAt DateTime?
hashedKey String @unique()
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
app App? @relation(fields: [appId], references: [slug], onDelete: Cascade)
appId String?
@@index([userId])
}
model HashedLink {
id Int @id @default(autoincrement())
link String @unique()
eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
eventTypeId Int @unique
}
model Account {
id String @id @default(cuid())
userId Int
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@index([userId])
@@index([type])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId Int
expires DateTime
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
enum AppCategories {
calendar
messaging
other
payment
video
web3
automation
analytics
}
model App {
// The slug for the app store public page inside `/apps/[slug]`
slug String @id @unique
// The directory name for `/packages/app-store/[dirName]`
dirName String @unique
// Needed API Keys
keys Json?
// One or multiple categories to which this app belongs
categories AppCategories[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
credentials Credential[]
payments Payment[]
Webhook Webhook[]
ApiKey ApiKey[]
enabled Boolean @default(false)
@@index([enabled])
}
model App_RoutingForms_Form {
id String @id @default(cuid())
description String?
routes Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
fields Json?
user User @relation("routing-form", fields: [userId], references: [id], onDelete: Cascade)
// This is the user who created the form and also the user who has read-write access to the form
// If teamId is set, the members of the team would also have access to form readOnly or read-write depending on their permission level as team member.
userId Int
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int?
responses App_RoutingForms_FormResponse[]
disabled Boolean @default(false)
/// @zod.custom(imports.RoutingFormSettings)
settings Json?
@@index([userId])
@@index([disabled])
}
model App_RoutingForms_FormResponse {
id Int @id @default(autoincrement())
formFillerId String @default(cuid())
form App_RoutingForms_Form @relation(fields: [formId], references: [id], onDelete: Cascade)
formId String
response Json
createdAt DateTime @default(now())
@@unique([formFillerId, formId])
@@index([formFillerId])
@@index([formId])
}
model Feedback {
id Int @id @default(autoincrement())
date DateTime @default(now())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
rating String
comment String?
@@index([userId])
@@index([rating])
}
enum WorkflowTriggerEvents {
BEFORE_EVENT
EVENT_CANCELLED
NEW_EVENT
AFTER_EVENT
RESCHEDULE_EVENT
}
enum WorkflowActions {
EMAIL_HOST
EMAIL_ATTENDEE
SMS_ATTENDEE
SMS_NUMBER
EMAIL_ADDRESS
}
model WorkflowStep {
id Int @id @default(autoincrement())
stepNumber Int
action WorkflowActions
workflowId Int
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
sendTo String?
reminderBody String?
emailSubject String?
template WorkflowTemplates @default(REMINDER)
workflowReminders WorkflowReminder[]
numberRequired Boolean?
sender String?
numberVerificationPending Boolean @default(true)
@@index([workflowId])
}
model Workflow {
id Int @id @default(autoincrement())
name String
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int?
activeOn WorkflowsOnEventTypes[]
trigger WorkflowTriggerEvents
time Int?
timeUnit TimeUnit?
steps WorkflowStep[]
@@index([userId])
@@index([teamId])
}
model WorkflowsOnEventTypes {
id Int @id @default(autoincrement())
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
workflowId Int
eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
eventTypeId Int
@@unique([workflowId, eventTypeId])
@@index([workflowId])
@@index([eventTypeId])
}
model Deployment {
/// This is a single row table, so we use a fixed id
id Int @id @default(1)
logo String?
/// @zod.custom(imports.DeploymentTheme)
theme Json?
licenseKey String?
agreedLicenseAt DateTime?
}
enum TimeUnit {
DAY @map("day")
HOUR @map("hour")
MINUTE @map("minute")
}
model WorkflowReminder {
id Int @id @default(autoincrement())
bookingUid String?
booking Booking? @relation(fields: [bookingUid], references: [uid])
method WorkflowMethods
scheduledDate DateTime
referenceId String? @unique
scheduled Boolean
workflowStepId Int?
workflowStep WorkflowStep? @relation(fields: [workflowStepId], references: [id])
cancelled Boolean?
@@index([bookingUid])
@@index([workflowStepId])
}
enum WorkflowTemplates {
REMINDER
CUSTOM
}
enum WorkflowMethods {
EMAIL
SMS
}
model BookingSeat {
id Int @id @default(autoincrement())
referenceUid String @unique
bookingId Int
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
attendeeId Int @unique
attendee Attendee @relation(fields: [attendeeId], references: [id], onDelete: Cascade)
data Json?
@@index([bookingId])
@@index([attendeeId])
}
model VerifiedNumber {
id Int @id @default(autoincrement())
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
phoneNumber String
@@index([userId])
@@index([teamId])
}
model Feature {
// The feature slug, ex: 'v2-workflows'
slug String @id @unique
// If the feature is currently enabled
enabled Boolean @default(false)
// A short description of the feature
description String?
// The type of feature flag
type FeatureType? @default(RELEASE)
// If the flag is considered stale
stale Boolean? @default(false)
lastUsedAt DateTime?
createdAt DateTime? @default(now())
updatedAt DateTime? @default(now()) @updatedAt
updatedBy Int?
@@index([enabled])
@@index([stale])
}
enum FeatureType {
RELEASE
EXPERIMENT
OPERATIONAL
KILL_SWITCH
PERMISSION
}
model SelectedSlots {
id Int @id @default(autoincrement())
eventTypeId Int
userId Int
slotUtcStartDate DateTime
slotUtcEndDate DateTime
uid String
releaseAt DateTime
isSeat Boolean @default(false)
@@unique(fields: [userId, slotUtcStartDate, slotUtcEndDate, uid], name: "selectedSlotUnique")
}
view BookingTimeStatus {
id Int @unique
uid String?
eventTypeId Int?
title String?
description String?
startTime DateTime?
endTime DateTime?
createdAt DateTime?
location String?
paid Boolean?
status BookingStatus?
rescheduled Boolean?
userId Int?
teamId Int?
eventLength Int?
timeStatus String?
}