-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Expand file tree
/
Copy pathschema.prisma
More file actions
2851 lines (2453 loc) · 98.7 KB
/
schema.prisma
File metadata and controls
2851 lines (2453 loc) · 98.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// 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")
directUrl = env("DATABASE_DIRECT_URL")
}
generator client {
provider = "prisma-client"
previewFeatures = ["views"]
output = "./generated/prisma"
engineType = "client"
moduleFormat = "cjs"
importFileExtension = ""
}
generator zod {
provider = "zod-prisma-types"
output = "./zod"
useMultipleFiles = true
createInputTypes = false
addIncludeType = false
addSelectType = false
validateWhereUniqueInput = false
prismaClientPath = "../../generated/prisma/client"
moduleFormat = "cjs"
/// createRelationValuesTypes = true
}
generator kysely {
provider = "prisma-kysely"
output = "../kysely"
fileName = "types.ts"
}
generator enums {
provider = "prisma-enum-generator"
}
enum SchedulingType {
ROUND_ROBIN @map("roundRobin")
COLLECTIVE @map("collective")
MANAGED @map("managed")
}
enum PeriodType {
UNLIMITED @map("unlimited")
ROLLING @map("rolling")
ROLLING_WINDOW @map("rolling_window")
RANGE @map("range")
}
enum CreationSource {
API_V1 @map("api_v1")
API_V2 @map("api_v2")
WEBAPP @map("webapp")
}
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)
priority Int?
weight Int?
// weightAdjustment is deprecated. We not calculate the calibratino value on the spot. Plan to drop this column.
weightAdjustment Int?
schedule Schedule? @relation(fields: [scheduleId], references: [id])
scheduleId Int?
createdAt DateTime @default(now())
group HostGroup? @relation(fields: [groupId], references: [id])
groupId String?
memberId Int?
member Membership? @relation(fields: [memberId], references: [id], onDelete: Cascade)
location HostLocation?
@@id([userId, eventTypeId])
@@index([memberId])
@@index([userId])
@@index([eventTypeId])
@@index([scheduleId])
}
model HostGroup {
id String @id @default(uuid())
name String
hosts Host[]
eventType EventType? @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
eventTypeId Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([name])
@@index([eventTypeId])
}
model HostLocation {
id String @id @default(uuid())
userId Int
eventTypeId Int
host Host @relation(fields: [userId, eventTypeId], references: [userId, eventTypeId], onDelete: Cascade)
type String
credentialId Int?
credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)
link String?
address String?
phoneNumber String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([userId, eventTypeId])
@@index([credentialId])
@@index([eventTypeId])
}
model CalVideoSettings {
eventTypeId Int @id
eventType EventType @relation(fields: [eventTypeId], references: [id], onDelete: Cascade)
disableRecordingForOrganizer Boolean @default(false)
disableRecordingForGuests Boolean @default(false)
enableAutomaticTranscription Boolean @default(false)
enableAutomaticRecordingForOrganizer Boolean @default(false)
redirectUrlOnExit String?
disableTranscriptionForGuests Boolean @default(false)
disableTranscriptionForOrganizer Boolean @default(false)
requireEmailForGuests Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model VideoCallGuest {
id String @id @default(uuid())
bookingUid String
email String
name String
joinedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([bookingUid, email])
@@index([bookingUid])
@@index([email])
}
enum CancellationReasonRequirement {
MANDATORY_BOTH
MANDATORY_HOST_ONLY
MANDATORY_ATTENDEE_ONLY
OPTIONAL_BOTH
}
model EventType {
id Int @id @default(autoincrement())
/// @zod.string.min(1)
title String
/// @zod.import(["import { eventTypeSlug } from '../../zod-utils'"]).custom.use(eventTypeSlug)
slug String
description String?
interfaceLanguage String?
position Int @default(0)
/// @zod.import(["import { eventTypeLocations } from '../../zod-utils'"]).custom.use(eventTypeLocations)
locations Json?
/// @zod.number.min(1)
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?
profileId Int?
profile Profile? @relation(fields: [profileId], references: [id])
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int?
hashedLink HashedLink[]
bookings Booking[]
availability Availability[]
webhooks Webhook[]
destinationCalendar DestinationCalendar?
useEventLevelSelectedCalendars Boolean @default(false)
eventName String?
customInputs EventTypeCustomInput[]
parentId Int?
parent EventType? @relation("managed_eventtype", fields: [parentId], references: [id], onDelete: Cascade)
children EventType[] @relation("managed_eventtype")
/// @zod.import(["import { eventTypeBookingFields } from '../../zod-utils'"]).custom.use(eventTypeBookingFields)
bookingFields Json?
timeZone String?
periodType PeriodType @default(UNLIMITED)
/// @zod.import(["import { coerceToDate } from '../../zod-utils'"]).custom.use(coerceToDate)
periodStartDate DateTime?
/// @zod.import(["import { coerceToDate } from '../../zod-utils'"]).custom.use(coerceToDate)
periodEndDate DateTime?
periodDays Int?
periodCountCalendarDays Boolean?
lockTimeZoneToggleOnBookingPage Boolean @default(false)
lockedTimeZone String?
requiresConfirmation Boolean @default(false)
requiresConfirmationWillBlockSlot Boolean @default(false)
requiresConfirmationForFreeEmail Boolean @default(false)
requiresBookerEmailVerification Boolean @default(false)
canSendCalVideoTranscriptionEmails Boolean @default(true)
autoTranslateDescriptionEnabled Boolean @default(false)
autoTranslateInstantMeetingTitleEnabled Boolean @default(true)
/// @zod.import(["import { recurringEventType } from '../../zod-utils'"]).custom.use(recurringEventType)
recurringEvent Json?
disableGuests Boolean @default(false)
hideCalendarNotes Boolean @default(false)
hideCalendarEventDetails Boolean @default(false)
/// @zod.number.min(0)
minimumBookingNotice Int @default(120)
beforeEventBuffer Int @default(0)
afterEventBuffer Int @default(0)
seatsPerTimeSlot Int?
onlyShowFirstAvailableSlot Boolean @default(false)
showOptimizedSlots Boolean? @default(false)
disableCancelling Boolean? @default(false)
disableRescheduling Boolean? @default(false)
/// @zod.number.min(0)
minimumRescheduleNotice Int?
seatsShowAttendees Boolean? @default(false)
seatsShowAvailabilityCount Boolean? @default(true)
schedulingType SchedulingType?
schedule Schedule? @relation(fields: [scheduleId], references: [id])
scheduleId Int?
allowReschedulingCancelledBookings Boolean? @default(false)
// 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.import(["import { EventTypeMetaDataSchema } from '../../zod-utils'"]).custom.use(EventTypeMetaDataSchema)
metadata Json?
/// @zod.import(["import { successRedirectUrl } from '../../zod-utils'"]).custom.use(successRedirectUrl)
successRedirectUrl String?
forwardParamsSuccessRedirect Boolean? @default(true)
/// @zod.import(["import { intervalLimitsType } from '../../zod-utils'"]).custom.use(intervalLimitsType)
bookingLimits Json?
/// @zod.import(["import { intervalLimitsType } from '../../zod-utils'"]).custom.use(intervalLimitsType)
durationLimits Json?
isInstantEvent Boolean @default(false)
instantMeetingExpiryTimeOffsetInSeconds Int @default(90)
instantMeetingScheduleId Int?
instantMeetingSchedule Schedule? @relation("InstantMeetingSchedule", fields: [instantMeetingScheduleId], references: [id])
instantMeetingParameters String[]
assignAllTeamMembers Boolean @default(false)
// It is applicable only when assignAllTeamMembers is true and it filters out all the team members using rrSegmentQueryValue
assignRRMembersUsingSegment Boolean @default(false)
/// @zod.import(["import { rrSegmentQueryValueSchema } from '../../zod-utils'"]).custom.use(rrSegmentQueryValueSchema)
rrSegmentQueryValue Json?
useEventTypeDestinationCalendarEmail Boolean @default(false)
isRRWeightsEnabled Boolean @default(false)
fieldTranslations EventTypeTranslation[]
maxLeadThreshold Int?
includeNoShowInRRCalculation Boolean @default(false)
selectedCalendars SelectedCalendar[]
allowReschedulingPastBookings Boolean @default(false)
hideOrganizerEmail Boolean @default(false)
maxActiveBookingsPerBooker Int?
maxActiveBookingPerBookerOfferReschedule Boolean @default(false)
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
customReplyToEmail String?
calVideoSettings CalVideoSettings?
/// @zod.import(["import { eventTypeColor } from '../../zod-utils'"]).custom.use(eventTypeColor)
eventTypeColor Json?
rescheduleWithSameRoundRobinHost Boolean @default(false)
secondaryEmailId Int?
secondaryEmail SecondaryEmail? @relation(fields: [secondaryEmailId], references: [id], onDelete: Cascade)
useBookerTimezone Boolean @default(false)
restrictionScheduleId Int?
restrictionSchedule Schedule? @relation("restrictionSchedule", fields: [restrictionScheduleId], references: [id])
hostGroups HostGroup[]
bookingRequiresAuthentication Boolean @default(false)
rrHostSubsetEnabled Boolean @default(false)
requiresCancellationReason CancellationReasonRequirement? @default(MANDATORY_HOST_ONLY)
enablePerHostLocations Boolean @default(false)
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
// @@partial_index([instantMeetingScheduleId])
@@unique([userId, slug])
@@unique([teamId, slug])
@@unique([userId, parentId])
@@index([userId])
@@index([teamId])
@@index([profileId])
@@index([scheduleId])
@@index([secondaryEmailId])
@@index([parentId])
@@index([parentId, teamId])
@@index([restrictionScheduleId])
}
model Credential {
id Int @id @default(autoincrement())
// @@type is deprecated
type String
key Json
encryptedKey String?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int?
app App? @relation(fields: [appId], references: [slug], onDelete: Cascade)
// How to make it a required column?
appId String?
// paid apps
subscriptionId String?
paymentStatus String?
billingCycleStart Int?
destinationCalendars DestinationCalendar[]
selectedCalendars SelectedCalendar[]
invalid Boolean? @default(false)
CalendarCache CalendarCache[]
references BookingReference[]
delegationCredentialId String?
delegationCredential DelegationCredential? @relation(fields: [delegationCredentialId], references: [id], onDelete: Cascade)
integrationAttributeSyncs IntegrationAttributeSync[]
hostLocations HostLocation[]
@@index([appId])
@@index([subscriptionId])
@@index([invalid])
@@index([userId, delegationCredentialId])
@@index([teamId])
}
enum IdentityProvider {
CAL
GOOGLE
SAML
AZUREAD
}
model DestinationCalendar {
id Int @id @default(autoincrement())
integration String
externalId String
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
primaryEmail 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)
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
delegationCredential DelegationCredential? @relation(fields: [delegationCredentialId], references: [id], onDelete: Cascade)
delegationCredentialId String?
customCalendarReminder Int?
@@index([userId])
@@index([eventTypeId])
@@index([credentialId])
}
enum UserPermissionRole {
USER
ADMIN
}
// It holds the password of a User, separate from the User model to avoid leaking the password hash
model UserPassword {
hash String
userId Int @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model TravelSchedule {
id Int @id @default(autoincrement())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
timeZone String
startDate DateTime
endDate DateTime?
prevTimeZone String?
@@index([startDate])
@@index([endDate])
}
// It holds Personal Profiles of a User plus it has email, password and other core things..
model User {
id Int @id @default(autoincrement())
uuid String @unique @default(uuid()) @db.Uuid
username String?
name String?
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
email String
emailVerified DateTime?
password UserPassword?
bio String?
avatarUrl String?
timeZone String @default("Europe/London")
travelSchedules TravelSchedule[]
weekStart String @default("Sunday")
bufferTime Int @default(0)
hideBranding Boolean @default(false)
// TODO: should be renamed since it only affects the booking page
theme String?
appTheme String?
createdDate DateTime @default(now()) @map(name: "created")
trialEndsAt DateTime?
lastActiveAt 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)
backupCodes String?
identityProvider IdentityProvider @default(CAL)
identityProviderId String?
availability Availability[]
invitedTo Int?
webhooks Webhook[]
brandColor String?
darkBrandColor String?
// the location where the events will end up
destinationCalendar DestinationCalendar?
// participate in dynamic group booking or not
allowDynamicBooking Boolean? @default(true)
// participate in SEO indexing or not
allowSEOIndexing Boolean? @default(true)
// receive monthly digest email for teams or not
receiveMonthlyDigestEmail Boolean? @default(true)
// require email verification when someone books using your email
requiresBookerEmailVerification Boolean? @default(false)
/// @zod.import(["import { userMetadata } from '../../zod-utils'"]).custom.use(userMetadata)
metadata Json?
verified Boolean? @default(false)
role UserPermissionRole @default(USER)
apiKeys ApiKey[]
accounts Account[]
sessions Session[]
Feedback Feedback[]
ownedEventTypes EventType[] @relation("owner")
verifiedNumbers VerifiedNumber[]
verifiedEmails VerifiedEmail[]
hosts Host[]
// organizationId is deprecated. Instead, rely on the Profile to search profiles by organizationId and then get user from the profile.
organizationId Int?
organization Team? @relation("scope", fields: [organizationId], references: [id], onDelete: SetNull)
accessCodes AccessCode[]
bookingRedirects OutOfOfficeEntry[]
bookingRedirectsTo OutOfOfficeEntry[] @relation(name: "toUser")
// Used to lock the user account
locked Boolean @default(false)
platformOAuthClients PlatformOAuthClient[]
AccessToken AccessToken[]
RefreshToken RefreshToken[]
PlatformAuthorizationToken PlatformAuthorizationToken[]
profiles Profile[]
movedToProfileId Int?
movedToProfile Profile? @relation("moved_to_profile", fields: [movedToProfileId], references: [id], onDelete: SetNull)
secondaryEmails SecondaryEmail[]
isPlatformManaged Boolean @default(false)
OutOfOfficeReasons OutOfOfficeReason[]
smsLockState SMSLockState @default(UNLOCKED)
smsLockReviewedByAdmin Boolean @default(false)
NotificationsSubscriptions NotificationsSubscriptions[]
referralLinkId String?
features UserFeatures[]
reassignedBookings Booking[] @relation("reassignByUser")
createdAttributeToUsers AttributeToUser[] @relation("createdBy")
updatedAttributeToUsers AttributeToUser[] @relation("updatedBy")
createdTranslations EventTypeTranslation[] @relation("CreatedEventTypeTranslations")
updatedTranslations EventTypeTranslation[] @relation("UpdatedEventTypeTranslations")
reportedBookings BookingReport[] @relation("ReportedBy")
wrongAssignmentReports WrongAssignmentReport[] @relation("WrongAssignmentReportedBy")
reviewedWrongAssignmentReports WrongAssignmentReport[] @relation("WrongAssignmentReviewedBy")
BookingInternalNote BookingInternalNote[]
creationSource CreationSource?
createdOrganizationOnboardings OrganizationOnboarding[] @relation("CreatedOrganizationOnboardings")
filterSegments FilterSegment[]
filterSegmentPreferences UserFilterSegmentPreference[]
creditBalance CreditBalance?
calAiPhoneNumbers CalAiPhoneNumber[]
agents Agent[]
oAuthClients OAuthClient[]
holidaySettings UserHolidaySettings?
autoOptInFeatures Boolean @default(false)
@@unique([email])
@@unique([email, username])
@@unique([username, organizationId])
@@unique([movedToProfileId])
@@index([username])
@@index([emailVerified])
@@index([identityProvider])
@@index([identityProviderId])
@@map(name: "users")
}
model NotificationsSubscriptions {
id Int @id @default(autoincrement())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
subscription String
@@index([userId, subscription])
}
// It holds Organization Profiles as well as User Profiles for users that have been added to an organization
model Profile {
id Int @id @default(autoincrement())
// uid allows us to set an identifier chosen by us which is helpful in migration when we create the Profile from User directly.
uid String
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
organizationId Int
organization Team @relation(fields: [organizationId], references: [id], onDelete: Cascade)
username String
eventTypes EventType[]
movedFromUser User? @relation("moved_to_profile")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// A user can have multiple profiles in different organizations
@@unique([userId, organizationId])
// Allow username reuse only across different organizations
@@unique([username, organizationId])
@@index([uid])
@@index([userId])
@@index([organizationId])
}
model Team {
id Int @id @default(autoincrement())
/// @zod.string.min(1)
name String
// It is unique across teams and organizations. We don't have a strong reason for organization and team slug to be conflicting, could be fixed.
// Sub-teams could have same slug across different organizations but not within the same organization.
/// @zod.string.min(1)
slug String?
logoUrl String?
calVideoLogo String?
appLogo String?
appIconLogo String?
bio String?
hideBranding Boolean @default(false)
hideTeamProfileLink Boolean @default(false)
isPrivate Boolean @default(false)
hideBookATeamMember Boolean @default(false)
members Membership[]
eventTypes EventType[]
createdAt DateTime @default(now())
/// @zod.import(["import { teamMetadataSchema } from '../../zod-utils'"]).custom.use(teamMetadataSchema)
metadata Json?
theme String?
rrResetInterval RRResetInterval? @default(MONTH)
rrTimestampBasis RRTimestampBasis @default(CREATED_AT)
brandColor String?
darkBrandColor String?
verifiedNumbers VerifiedNumber[]
verifiedEmails VerifiedEmail[]
bannerUrl String?
parentId Int?
parent Team? @relation("organization", fields: [parentId], references: [id], onDelete: Cascade)
children Team[] @relation("organization")
orgUsers User[] @relation("scope")
inviteTokens VerificationToken[]
webhooks Webhook[]
timeFormat Int?
timeZone String @default("Europe/London")
weekStart String @default("Sunday")
apiKeys ApiKey[]
credentials Credential[]
accessCodes AccessCode[]
isOrganization Boolean @default(false)
organizationSettings OrganizationSettings?
instantMeetingTokens InstantMeetingToken[]
orgProfiles Profile[]
pendingPayment Boolean @default(false)
dsyncTeamGroupMapping DSyncTeamGroupMapping[]
isPlatform Boolean @default(false)
// Organization's OAuth clients. Organization has them but a team does not.
platformOAuthClient PlatformOAuthClient[]
// OAuth client used to create team of an organization. Team has it but organization does not.
createdByOAuthClient PlatformOAuthClient? @relation("CreatedByOAuthClient", fields: [createdByOAuthClientId], references: [id], onDelete: Cascade)
createdByOAuthClientId String?
smsLockState SMSLockState @default(UNLOCKED)
platformBilling PlatformBilling?
attributes Attribute[]
smsLockReviewedByAdmin Boolean @default(false)
// Available for Organization only
delegationCredentials DelegationCredential[]
roles Role[] // Added for Role relation
calAiPhoneNumbers CalAiPhoneNumber[]
agents Agent[]
bookingReports BookingReport[]
wrongAssignmentReports WrongAssignmentReport[]
features TeamFeatures[]
/// @zod.import(["import { intervalLimitsType } from '../../zod-utils'"]).custom.use(intervalLimitsType)
bookingLimits Json?
includeManagedEventsInLimits Boolean @default(false)
internalNotePresets InternalNotePreset[]
creditBalance CreditBalance?
organizationOnboarding OrganizationOnboarding?
// note(Lauris): if a Team has parentId it is a team, if parentId is null it is an organization, but if parentId is null and managedOrganization is set,
// it means that it is an organization managed by another organization.
managedOrganization ManagedOrganization? @relation("ManagedOrganization")
managedOrganizations ManagedOrganization[] @relation("ManagerOrganization")
filterSegments FilterSegment[]
teamBilling TeamBilling? @relation("TeamBilling")
organizationBilling OrganizationBilling? @relation("OrganizationBilling")
integrationAttributeSyncs IntegrationAttributeSync[]
autoOptInFeatures Boolean @default(false)
// Monthly proration tracking
seatChangeLogs SeatChangeLog[]
monthlyProrations MonthlyProration[]
@@unique([slug, parentId])
@@index([parentId])
}
model CreditBalance {
id String @id @default(uuid())
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int? @unique
// user credit balances will be supported in the future
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int? @unique
additionalCredits Int @default(0)
limitReachedAt DateTime?
warningSentAt DateTime?
expenseLogs CreditExpenseLog[]
purchaseLogs CreditPurchaseLog[]
}
model CreditPurchaseLog {
id String @id @default(uuid())
creditBalanceId String
creditBalance CreditBalance @relation(fields: [creditBalanceId], references: [id], onDelete: Cascade)
credits Int
createdAt DateTime @default(now())
}
enum CreditUsageType {
SMS
CAL_AI_PHONE_CALL
}
model CreditExpenseLog {
id String @id @default(uuid())
creditBalanceId String
creditBalance CreditBalance @relation(fields: [creditBalanceId], references: [id], onDelete: Cascade)
bookingUid String?
booking Booking? @relation(fields: [bookingUid], references: [uid], onDelete: Cascade)
credits Int?
creditType CreditType
date DateTime
smsSid String?
smsSegments Int?
phoneNumber String?
email String?
callDuration Int?
creditFor CreditUsageType?
externalRef String? @unique
// @@partial_index([bookingUid])
}
enum CreditType {
MONTHLY
ADDITIONAL
}
model OrganizationSettings {
id Int @id @default(autoincrement())
organization Team @relation(fields: [organizationId], references: [id], onDelete: Cascade)
organizationId Int @unique
isOrganizationConfigured Boolean @default(false)
// It decides if new organization members can be auto-accepted or not
isOrganizationVerified Boolean @default(false)
// It is a domain e.g "acme.com". Any email with this domain might be auto-accepted
// Also, it is the domain to which the organization profile is redirected.
orgAutoAcceptEmail String
lockEventTypeCreationForUsers Boolean @default(false)
adminGetsNoSlotsNotification Boolean @default(false)
// It decides if instance ADMIN has reviewed the organization or not.
// It is used to allow super sensitive operations like 'impersonation of Org members by Org admin'
isAdminReviewed Boolean @default(false)
dSyncData DSyncData?
isAdminAPIEnabled Boolean @default(false)
allowSEOIndexing Boolean @default(false)
orgProfileRedirectsToVerifiedDomain Boolean @default(false)
disablePhoneOnlySMSNotifications Boolean @default(false)
disableAutofillOnBookingPage Boolean @default(false)
orgAutoJoinOnSignup Boolean @default(true)
disableAttendeeConfirmationEmail Boolean @default(false)
disableAttendeeCancellationEmail Boolean @default(false)
disableAttendeeRescheduledEmail Boolean @default(false)
disableAttendeeRequestEmail Boolean @default(false)
disableAttendeeReassignedEmail Boolean @default(false)
disableAttendeeAwaitingPaymentEmail Boolean @default(false)
disableAttendeeRescheduleRequestEmail Boolean @default(false)
disableAttendeeLocationChangeEmail Boolean @default(false)
disableAttendeeNewEventEmail Boolean @default(false)
}
enum MembershipRole {
MEMBER
ADMIN
OWNER
}
model Membership {
id Int @id @default(autoincrement())
teamId Int
userId Int
accepted Boolean @default(false)
role MembershipRole
customRoleId String?
customRole Role? @relation(fields: [customRoleId], references: [id])
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
AttributeToUser AttributeToUser[]
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
Host Host[]
@@unique([userId, teamId])
@@index([teamId])
@@index([userId])
@@index([accepted])
@@index([role])
@@index([customRoleId])
}
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?
team Team? @relation(fields: [teamId], references: [id])
secondaryEmailId Int?
secondaryEmail SecondaryEmail? @relation(fields: [secondaryEmailId], references: [id])
@@unique([identifier, token])
@@index([token])
@@index([teamId])
@@index([secondaryEmailId])
}
model InstantMeetingToken {
id Int @id @default(autoincrement())
token String @unique
expires DateTime
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
bookingId Int? @unique
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([token])
}
model BookingReference {
id Int @id @default(autoincrement())
/// @zod.string.min(1)
type String
/// @zod.string.min(1)
uid String
meetingId String?
thirdPartyRecurringEventId String?
meetingPassword String?
meetingUrl String?
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
bookingId Int?
externalCalendarId String?
deleted Boolean?
credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)
credentialId Int?
delegationCredential DelegationCredential? @relation(fields: [delegationCredentialId], references: [id], onDelete: SetNull)
delegationCredentialId String?
@@index([bookingId])
@@index([type])
@@index([uid])
}
model Attendee {
id Int @id @default(autoincrement())
email String
name String
timeZone String
phoneNumber String?
locale String? @default("en")
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
bookingId Int?
bookingSeat BookingSeat?
noShow Boolean? @default(false)
@@index([email])
@@index([bookingId])
@@index([email, bookingId])
}
enum BookingStatus {
CANCELLED @map("cancelled")
ACCEPTED @map("accepted")
REJECTED @map("rejected")
PENDING @map("pending")
AWAITING_HOST @map("awaiting_host")
}
model Booking {
id Int @id @default(autoincrement())
uid String @unique
// (optional) UID based on slot start/end time & email against duplicates
idempotencyKey String? @unique
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int?
// User's email at the time of booking
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
userPrimaryEmail String?
references BookingReference[]
eventType EventType? @relation(fields: [eventTypeId], references: [id])
eventTypeId Int?
title String
description String?
customInputs Json?
/// @zod.import(["import { bookingResponses } from '../../zod-utils'"]).custom.use(bookingResponses)
responses Json?
startTime DateTime
endTime DateTime
attendees Attendee[]
location String?
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
status BookingStatus @default(ACCEPTED)
paid Boolean @default(false)
payment Payment[]
destinationCalendar DestinationCalendar? @relation(fields: [destinationCalendarId], references: [id])
destinationCalendarId Int?
cancellationReason String?
rejectionReason String?
reassignReason String?
reassignBy User? @relation("reassignByUser", fields: [reassignById], references: [id])
reassignById Int?
dynamicEventSlugRef String?
dynamicGroupSlugRef String?
rescheduled Boolean?
fromReschedule String?
recurringEventId String?
smsReminderNumber String?
scheduledJobs String[] // scheduledJobs is deprecated, please use scheduledTriggers instead
seatsReferences BookingSeat[]
/// @zod.import(["import { bookingMetadataSchema } from '../../zod-utils'"]).custom.use(bookingMetadataSchema)
metadata Json?
isRecorded Boolean @default(false)
iCalUID String? @default("")
iCalSequence Int @default(0)
instantMeetingToken InstantMeetingToken?
rating Int?
ratingFeedback String?
noShowHost Boolean? @default(false)
scheduledTriggers WebhookScheduledTriggers[]
oneTimePassword String? @unique @default(uuid())
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
cancelledBy String?
/// @zod.import(["import { emailSchema } from '../../zod-utils'"]).custom.use(emailSchema)
rescheduledBy String?
assignmentReason AssignmentReason[]
internalNote BookingInternalNote[]
creationSource CreationSource?
tracking Tracking?
expenseLogs CreditExpenseLog[]
report BookingReport?
wrongAssignmentReports WrongAssignmentReport[]
// @@partial_index([reassignById])
@@index([eventTypeId])
@@index([userId])
@@index([destinationCalendarId])
@@index([recurringEventId])
@@index([uid])
@@index([status])
@@index([startTime, endTime, status])
@@index([fromReschedule])
@@index([userId, endTime])
@@index([userId, status, startTime])
@@index([eventTypeId, status])
@@index([userId, createdAt])
}
model Tracking {
id Int @id @default(autoincrement())
bookingId Int
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
utm_source String?
utm_medium String?
utm_campaign String?
utm_term String?
utm_content String?
@@unique([bookingId])
}
model Schedule {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
eventType EventType[]
instantMeetingEvents EventType[] @relation("InstantMeetingSchedule")
restrictionSchedule EventType[] @relation("restrictionSchedule")
name String
timeZone String?
availability Availability[]
Host Host[]
@@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 {
id String @id @default(uuid())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
integration String
externalId String
credential Credential? @relation(fields: [credentialId], references: [id], onDelete: Cascade)
credentialId Int?
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt
// Used to identify a watched calendar channel in Google Calendar
// @deprecated use channelId instead
googleChannelId String?
// @deprecated use channelKind instead
googleChannelKind String?
// @deprecated use channelResourceId instead
googleChannelResourceId String?
// @deprecated use channelResourceUri instead
googleChannelResourceUri String?