Created
April 25, 2023 20:12
-
-
Save AlexandroMtzG/3093d30b525eda1036b2083f6c176cdb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
generator client { | |
provider = "prisma-client-js" | |
previewFeatures = ["jsonProtocol"] | |
} | |
datasource db { | |
provider = "postgresql" | |
url = env("DATABASE_URL") | |
} | |
model AppConfiguration { | |
id String @id @default(cuid()) | |
updatedAt DateTime @updatedAt | |
name String | |
url String | |
authRequireEmailVerification Boolean @default(false) | |
authRequireOrganization Boolean @default(true) | |
authRequireName Boolean @default(true) | |
authRecaptchaSiteKey String? | |
analyticsEnabled Boolean @default(true) | |
analyticsSimpleAnalytics Boolean @default(false) | |
analyticsPlausibleAnalytics Boolean @default(false) | |
analyticsGoogleAnalyticsTrackingId String? | |
subscriptionRequired Boolean @default(true) | |
subscriptionAllowSubscribeBeforeSignUp Boolean @default(true) | |
subscriptionAllowSignUpBeforeSubscribe Boolean @default(true) | |
cookiesEnabled Boolean @default(false) | |
} | |
model AppCookie { | |
id String @id @default(cuid()) | |
category Int | |
name String | |
description String | |
enabled Boolean @default(true) | |
expiry String? | |
domain String? | |
type String? | |
href String? | |
} | |
model User { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
email String @unique | |
passwordHash String | |
firstName String | |
lastName String | |
avatar String? | |
phone String? | |
defaultTenantId String? | |
verifyToken String? | |
githubId String? @unique | |
googleId String? @unique | |
locale String? | |
active Boolean @default(false) | |
admin AdminUser? // Has access to the admin panel | |
createdApiKeys ApiKey[] | |
workflowSteps EntityWorkflowStepAssignee[] | |
createdGroups Group[] | |
groups GroupUser[] | |
createdLinkedAccounts LinkedAccount[] | |
logs Log[] | |
createdRows Row[] | |
createdRowComments RowComment[] | |
createdRowCommentReactions RowCommentReaction[] | |
createdEntityViews EntityView[] @relation("createdByUser") | |
rowPermissions RowPermission[] | |
assignedTasks RowTask[] @relation("assignedToUser") | |
completedTasks RowTask[] @relation("completedByUser") | |
createdRowTasks RowTask[] @relation("createdByUser") | |
workflowTransitions RowWorkflowTransition[] | |
tenants TenantUser[] | |
invitation TenantUserInvitation? | |
roles UserRole[] | |
readEmails EmailRead[] | |
entityViews EntityView[] | |
onboardingSessions OnboardingSession[] | |
tags TagUser[] | |
tenantIpAddresses TenantIpAddress[] | |
} | |
// Has access to the admin panel | |
model AdminUser { | |
userId String @unique | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model Tenant { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
slug String @unique | |
name String | |
icon String? | |
subscriptionId String? | |
active Boolean @default(false) | |
deactivatedReason String? | |
apiKeys ApiKey[] | |
workflowSteps EntityWorkflowStepAssignee[] | |
groups Group[] | |
asClientLinkedAccounts LinkedAccount[] @relation("clientTenant") | |
createdLinkedAccounts LinkedAccount[] @relation("createdByTenant") | |
asProviderLinkedAccounts LinkedAccount[] @relation("providerTenant") | |
logs Log[] | |
rows Row[] | |
rowPermissions RowPermission[] | |
subscription TenantSubscription? | |
users TenantUser[] | |
invitations TenantUserInvitation[] | |
userRoles UserRole[] | |
inboundAddresses TenantInboundAddress[] | |
events Event[] | |
fromRegistration Registration? | |
entityViews EntityView[] | |
emailSenders EmailSender[] | |
campaigns Campaign[] | |
outboundEmails OutboundEmail[] | |
tags TagTenant[] | |
onboardingSessions OnboardingSession[] | |
ipAddresses TenantIpAddress[] | |
tenantSettingsRow TenantSettingsRow? | |
} | |
model Registration { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
email String @unique | |
firstName String | |
lastName String | |
token String @unique | |
ipAddress String? | |
company String? | |
selectedSubscriptionPriceId String? | |
createdTenantId String? @unique | |
createdTenant Tenant? @relation(fields: [createdTenantId], references: [id], onDelete: Cascade) | |
} | |
model Blacklist { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
type String // email, domain, ip | |
value String | |
active Boolean @default(true) | |
registerAttempts Int @default(0) | |
} | |
model TenantSubscription { | |
id String @id @default(cuid()) | |
tenantId String @unique | |
stripeCustomerId String? | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
products TenantSubscriptionProduct[] | |
} | |
model TenantSubscriptionProduct { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
tenantSubscriptionId String | |
subscriptionProductId String | |
cancelledAt DateTime? | |
endsAt DateTime? | |
stripeSubscriptionId String? | |
quantity Int? | |
fromCheckoutSessionId String? | |
tenantSubscription TenantSubscription @relation(fields: [tenantSubscriptionId], references: [id], onDelete: Cascade) | |
subscriptionProduct SubscriptionProduct @relation(fields: [subscriptionProductId], references: [id]) | |
prices TenantSubscriptionProductPrice[] | |
} | |
model TenantSubscriptionProductPrice { | |
id String @id @default(cuid()) | |
tenantSubscriptionProductId String | |
tenantSubscriptionProduct TenantSubscriptionProduct @relation(fields: [tenantSubscriptionProductId], references: [id], onDelete: Cascade) | |
subscriptionPriceId String? | |
subscriptionPrice SubscriptionPrice? @relation(fields: [subscriptionPriceId], references: [id]) | |
subscriptionUsageBasedPriceId String? | |
subscriptionUsageBasedPrice SubscriptionUsageBasedPrice? @relation(fields: [subscriptionUsageBasedPriceId], references: [id]) | |
usageRecords TenantSubscriptionUsageRecord[] | |
} | |
model TenantSubscriptionUsageRecord { | |
id String @id @default(cuid()) | |
tenantSubscriptionProductPriceId String | |
tenantSubscriptionProductPrice TenantSubscriptionProductPrice @relation(fields: [tenantSubscriptionProductPriceId], references: [id], onDelete: Cascade) | |
timestamp Int | |
quantity Int | |
stripeSubscriptionItemId String? | |
} | |
model CheckoutSessionStatus { | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
id String @unique | |
pending Boolean @default(true) // has not added products to tenant | |
email String | |
fromUrl String | |
fromUserId String? | |
fromTenantId String? | |
createdUserId String? | |
createdTenantId String? | |
} | |
model TenantUser { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
tenantId String | |
userId String | |
type Int | |
joined Int | |
status Int | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
roles TenantUserRole[] | |
} | |
model Role { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
name String @unique | |
description String | |
type String | |
assignToNewUsers Boolean | |
isDefault Boolean | |
order Int | |
workflowSteps EntityWorkflowStepAssignee[] | |
permissions RolePermission[] | |
rowPermissions RowPermission[] | |
users UserRole[] | |
} | |
model Permission { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
name String @unique | |
description String | |
type String | |
isDefault Boolean | |
order Int | |
inRoles RolePermission[] | |
entityId String? | |
entity Entity? @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
} | |
model RolePermission { | |
id String @id @default(cuid()) | |
roleId String | |
permissionId String | |
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) | |
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) | |
} | |
model UserRole { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
userId String | |
roleId String | |
tenantId String? | |
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model Group { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
tenantId String? | |
name String | |
description String | |
color Int | |
createdByUser User @relation(fields: [createdByUserId], references: [id], onDelete: Cascade) | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
workflowSteps EntityWorkflowStepAssignee[] | |
users GroupUser[] | |
rowPermissions RowPermission[] | |
} | |
model GroupUser { | |
id String @id @default(cuid()) | |
groupId String | |
userId String | |
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model TenantUserRole { | |
id String @id @default(cuid()) | |
tenantUserId String | |
order Int | |
name String | |
tenantUser TenantUser @relation(fields: [tenantUserId], references: [id], onDelete: Cascade) | |
} | |
model TenantUserInvitation { | |
id String @id @default(cuid()) | |
tenantId String | |
email String | |
firstName String | |
lastName String | |
type Int | |
pending Boolean | |
createdUserId String? @unique | |
user User? @relation(fields: [createdUserId], references: [id], onDelete: Cascade) | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
} | |
model LinkedAccount { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
createdByTenantId String | |
providerTenantId String | |
clientTenantId String | |
status Int | |
clientTenant Tenant @relation("clientTenant", fields: [clientTenantId], references: [id], onDelete: Cascade) | |
createdByTenant Tenant @relation("createdByTenant", fields: [createdByTenantId], references: [id], onDelete: Cascade) | |
createdByUser User @relation(fields: [createdByUserId], references: [id], onDelete: Cascade) | |
providerTenant Tenant @relation("providerTenant", fields: [providerTenantId], references: [id], onDelete: Cascade) | |
} | |
model ApiKey { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
tenantId String | |
key String @default(uuid()) | |
alias String | |
expires DateTime? | |
active Boolean | |
createdByUser User @relation(fields: [createdByUserId], references: [id], onDelete: Cascade) | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
entities ApiKeyEntity[] | |
apiKeyLogs ApiKeyLog[] | |
logs Log[] | |
createdRows Row[] | |
transitions RowWorkflowTransition[] | |
tenantIpAddresses TenantIpAddress[] | |
@@unique([tenantId, alias]) | |
} | |
model ApiKeyEntity { | |
id String @id @default(cuid()) | |
apiKeyId String | |
entityId String | |
create Boolean | |
read Boolean | |
update Boolean | |
delete Boolean | |
apiKey ApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade) | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
} | |
model Log { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
tenantId String? | |
userId String? | |
apiKeyId String? | |
rowId String? | |
url String | |
action String | |
details String? | |
commentId String? | |
workflowTransitionId String? | |
apiKey ApiKey? @relation(fields: [apiKeyId], references: [id], onDelete: Cascade) | |
comment RowComment? @relation(fields: [commentId], references: [id]) | |
row Row? @relation(fields: [rowId], references: [id]) | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
user User? @relation(fields: [userId], references: [id], onDelete: Cascade) | |
workflowTransition RowWorkflowTransition? @relation(fields: [workflowTransitionId], references: [id]) | |
webhookLogs EntityWebhookLog[] | |
} | |
model ApiKeyLog { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
apiKeyId String? | |
ip String | |
endpoint String | |
method String | |
params String | |
status Int? | |
error String? | |
apiKey ApiKey? @relation(fields: [apiKeyId], references: [id], onDelete: Cascade) | |
} | |
model SubscriptionProduct { | |
id String @id @default(cuid()) | |
stripeId String | |
order Int | |
title String | |
active Boolean | |
model Int | |
public Boolean | |
groupTitle String? | |
groupDescription String? | |
description String? | |
badge String? | |
prices SubscriptionPrice[] | |
features SubscriptionFeature[] | |
tenantProducts TenantSubscriptionProduct[] | |
usageBasedPrices SubscriptionUsageBasedPrice[] | |
} | |
model SubscriptionPrice { | |
id String @id @default(cuid()) | |
subscriptionProductId String | |
subscriptionProduct SubscriptionProduct @relation(fields: [subscriptionProductId], references: [id], onDelete: Cascade) | |
stripeId String | |
type Int | |
billingPeriod Int | |
price Decimal | |
currency String | |
trialDays Int | |
active Boolean | |
tenantProductPrices TenantSubscriptionProductPrice[] | |
} | |
model SubscriptionUsageBasedPrice { | |
id String @id @default(cuid()) | |
subscriptionProductId String | |
subscriptionProduct SubscriptionProduct @relation(fields: [subscriptionProductId], references: [id], onDelete: Cascade) | |
stripeId String | |
billingPeriod Int | |
currency String | |
unit String | |
unitTitle String | |
unitTitlePlural String | |
usageType String | |
aggregateUsage String | |
tiersMode String | |
billingScheme String | |
tiers SubscriptionUsageBasedTier[] | |
tenantProductPrices TenantSubscriptionProductPrice[] | |
} | |
model SubscriptionUsageBasedTier { | |
id String @id @default(cuid()) | |
subscriptionUsageBasedPriceId String | |
subscriptionUsageBasedPrice SubscriptionUsageBasedPrice @relation(fields: [subscriptionUsageBasedPriceId], references: [id], onDelete: Cascade) | |
from Int | |
to Int? | |
perUnitPrice Decimal? | |
flatFeePrice Decimal? | |
} | |
model SubscriptionFeature { | |
id String @id @default(cuid()) | |
subscriptionProductId String | |
order Int | |
title String | |
name String | |
type Int | |
value Int | |
href String? | |
subscriptionProduct SubscriptionProduct @relation(fields: [subscriptionProductId], references: [id], onDelete: Cascade) | |
} | |
model BlogAuthor { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
slug String @unique | |
firstName String | |
lastName String | |
image String | |
url String | |
posts BlogPost[] | |
} | |
model BlogCategory { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
name String @unique | |
color Int | |
posts BlogPost[] | |
} | |
model BlogTag { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
name String @unique | |
color Int | |
posts BlogPostTag[] | |
} | |
model BlogPostTag { | |
id String @id @default(cuid()) | |
postId String | |
tagId String | |
post BlogPost @relation(fields: [postId], references: [id], onDelete: Cascade) | |
tag BlogTag @relation(fields: [tagId], references: [id], onDelete: Cascade) | |
} | |
model BlogPost { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
slug String @unique | |
title String | |
description String | |
date DateTime | |
image String | |
content String | |
readingTime String | |
published Boolean | |
authorId String | |
categoryId String | |
author BlogAuthor @relation(fields: [authorId], references: [id], onDelete: Cascade) | |
category BlogCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade) | |
tags BlogPostTag[] | |
} | |
// <--- START: Entities ---> | |
// TODO: Wrap entities in modules (e.g. CRM, HelpDesk...) | |
model Module { | |
id String @id @default(cuid()) | |
type String @default("app") // app, admin, all | |
order Int | |
name String @unique | |
title String | |
description String | |
icon String | |
entities Entity[] | |
} | |
model Entity { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
moduleId String? | |
name String @unique | |
slug String @unique | |
order Int | |
prefix String @unique | |
type String @default("app") // app, admin, all | |
title String | |
titlePlural String | |
isAutogenerated Boolean | |
hasApi Boolean | |
icon String | |
active Boolean | |
showInSidebar Boolean @default(true) | |
hasTags Boolean @default(true) | |
hasComments Boolean @default(true) | |
hasTasks Boolean @default(true) | |
hasWorkflow Boolean @default(false) | |
defaultVisibility String @default("private") | |
createdPermissions Permission[] | |
apiKeys ApiKeyEntity[] | |
tags EntityTag[] | |
permissions EntityTenantUserPermission[] | |
webhooks EntityWebhook[] | |
workflowStates EntityWorkflowState[] | |
workflowSteps EntityWorkflowStep[] | |
properties Property[] | |
rows Row[] | |
views EntityView[] | |
parentEntities EntityRelationship[] @relation(name: "childEntities") | |
childEntities EntityRelationship[] @relation(name: "parentEntities") | |
module Module? @relation(fields: [moduleId], references: [id]) | |
} | |
model Property { | |
id String @id @default(cuid()) | |
entityId String | |
order Int | |
name String | |
title String | |
type Int | |
subtype String? | |
formula String? | |
isDynamic Boolean | |
isDefault Boolean | |
isRequired Boolean | |
isHidden Boolean | |
isDisplay Boolean @default(false) | |
isUnique Boolean @default(false) // TODO: Validate uniqueness | |
isReadOnly Boolean @default(false) | |
showInCreate Boolean @default(true) | |
attributes PropertyAttribute[] | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
options PropertyOption[] | |
values RowValue[] | |
inViewProperties EntityViewProperty[] | |
inViewGroupBy EntityView[] | |
@@unique([entityId, name]) | |
@@unique([entityId, title]) | |
} | |
model EntityView { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
createdByUserId String? | |
createdByUser User? @relation(name: "createdByUser", fields: [createdByUserId], references: [id]) | |
entityId String | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
tenantId String? | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
userId String? | |
user User? @relation(fields: [userId], references: [id], onDelete: Cascade) | |
layout String @default("table") // table, board, calendar, list, gallery... | |
order Int | |
name String | |
title String | |
pageSize Int | |
isDefault Boolean | |
columns Int? | |
properties EntityViewProperty[] | |
filters EntityViewFilter[] | |
sort EntityViewSort[] | |
groupByWorkflowStates Boolean @default(false) | |
groupByPropertyId String? | |
groupByProperty Property? @relation(fields: [groupByPropertyId], references: [id], onDelete: Cascade) | |
} | |
model EntityViewProperty { | |
id String @id @default(cuid()) | |
entityViewId String | |
entityView EntityView @relation(fields: [entityViewId], references: [id], onDelete: Cascade) | |
propertyId String? | |
property Property? @relation(fields: [propertyId], references: [id], onDelete: Cascade) | |
name String? // if not a property, e.g. "default.folio" | |
order Int | |
} | |
model EntityViewFilter { | |
id String @id @default(cuid()) | |
entityViewId String | |
entityView EntityView @relation(fields: [entityViewId], references: [id], onDelete: Cascade) | |
match String @default("and") // and, or | |
name String | |
condition String // is, isNot, contains, doesNotContain... | |
value String | |
} | |
model EntityViewSort { | |
id String @id @default(cuid()) | |
entityViewId String | |
entityView EntityView @relation(fields: [entityViewId], references: [id], onDelete: Cascade) | |
name String | |
asc Boolean | |
order Int | |
} | |
model PropertyAttribute { | |
id String @id @default(cuid()) | |
propertyId String | |
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) | |
name String // pattern, min, max, step, rows, defaultValue, maxSize, acceptFileTypes, uppercase... | |
value String | |
@@unique([propertyId, name]) | |
} | |
model PropertyOption { | |
id String @id @default(cuid()) | |
propertyId String | |
order Int | |
value String | |
name String? | |
color Int @default(0) | |
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) | |
// values RowValueSelection[] | |
} | |
model EntityTag { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
entityId String | |
value String | |
color Int | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
rowTags RowTag[] | |
} | |
model EntityTenantUserPermission { | |
id String @id @default(cuid()) | |
entityId String | |
level Int | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
} | |
model EntityWebhook { | |
id String @id @default(cuid()) | |
entityId String | |
action String | |
method String | |
endpoint String | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
logs EntityWebhookLog[] | |
} | |
model EntityWebhookLog { | |
id String @id @default(cuid()) | |
webhookId String | |
logId String | |
status Int | |
error String? | |
log Log @relation(fields: [logId], references: [id], onDelete: Cascade) | |
webhook EntityWebhook @relation(fields: [webhookId], references: [id], onDelete: Cascade) | |
} | |
model EntityWorkflowState { | |
id String @id @default(cuid()) | |
entityId String | |
order Int | |
name String | |
title String | |
color Int | |
canUpdate Boolean | |
canDelete Boolean | |
emailSubject String | |
emailBody String | |
progress Int? | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
fromStates EntityWorkflowStep[] @relation("fromState") | |
toStates EntityWorkflowStep[] @relation("toState") | |
rows Row[] | |
} | |
model EntityWorkflowStep { | |
id String @id @default(cuid()) | |
entityId String | |
action String | |
fromStateId String | |
toStateId String | |
assignTo String @default("private") | |
entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade) | |
fromState EntityWorkflowState @relation("fromState", fields: [fromStateId], references: [id], onDelete: Cascade) | |
toState EntityWorkflowState @relation("toState", fields: [toStateId], references: [id], onDelete: Cascade) | |
assignees EntityWorkflowStepAssignee[] | |
transitions RowWorkflowTransition[] | |
} | |
model EntityWorkflowStepAssignee { | |
id String @id @default(cuid()) | |
stepId String | |
tenantId String? | |
roleId String? | |
groupId String? | |
userId String? | |
group Group? @relation(fields: [groupId], references: [id], onDelete: Cascade) | |
role Role? @relation(fields: [roleId], references: [id], onDelete: Cascade) | |
step EntityWorkflowStep @relation(fields: [stepId], references: [id], onDelete: Cascade) | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
user User? @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model EntityRelationship { | |
id String @id @default(cuid()) | |
parentId String | |
parent Entity @relation(name: "parentEntities", fields: [parentId], references: [id], onDelete: Cascade) | |
childId String | |
child Entity @relation(name: "childEntities", fields: [childId], references: [id], onDelete: Cascade) | |
multiple Boolean | |
required Boolean | |
rows RowRelationship[] | |
input String? @default("table") | |
@@unique([parentId, childId]) | |
} | |
model SampleCustomEntity { | |
rowId String @unique | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
customText String | |
customNumber Decimal | |
customDate DateTime | |
customBoolean Boolean | |
customSelect String | |
} | |
model RowRelationship { | |
id String @id @default(cuid()) | |
relationshipId String | |
relationship EntityRelationship @relation(fields: [relationshipId], references: [id], onDelete: Cascade) | |
parentId String | |
parent Row @relation(name: "parentRow", fields: [parentId], references: [id], onDelete: Cascade) | |
childId String | |
child Row @relation(name: "childRow", fields: [childId], references: [id], onDelete: Cascade) | |
@@unique([parentId, childId]) | |
} | |
model Row { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
entityId String | |
tenantId String? | |
folio Int | |
createdByUserId String? | |
createdByApiKeyId String? | |
workflowStateId String? | |
createdByApiKey ApiKey? @relation(fields: [createdByApiKeyId], references: [id]) | |
createdByUser User? @relation(fields: [createdByUserId], references: [id]) | |
entity Entity @relation(fields: [entityId], references: [id]) | |
tenant Tenant? @relation(fields: [tenantId], references: [id]) | |
workflowState EntityWorkflowState? @relation(fields: [workflowStateId], references: [id]) | |
logs Log[] | |
comments RowComment[] | |
permissions RowPermission[] | |
tags RowTag[] | |
tasks RowTask[] | |
values RowValue[] | |
transitions RowWorkflowTransition[] | |
childRows RowRelationship[] @relation("parentRow") | |
parentRows RowRelationship[] @relation("childRow") | |
sampleCustomEntity SampleCustomEntity? | |
outboundEmails OutboundEmail[] | |
tenantSettingsRow TenantSettingsRow[] | |
} | |
model RowValue { | |
id String @id @default(cuid()) | |
rowId String | |
propertyId String | |
textValue String? | |
numberValue Decimal? | |
dateValue DateTime? | |
booleanValue Boolean? | |
// selection RowValueSelection[] // TODO: MULTI SELECT | |
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
media RowMedia[] | |
multiple RowValueMultiple[] | |
range RowValueRange? | |
} | |
model RowValueMultiple { | |
id String @id @default(cuid()) | |
rowValueId String | |
order Int | |
value String | |
rowValue RowValue @relation(fields: [rowValueId], references: [id], onDelete: Cascade) | |
} | |
model RowValueRange { | |
rowValueId String @unique | |
numberMin Decimal? | |
numberMax Decimal? | |
dateMin DateTime? | |
dateMax DateTime? | |
rowValue RowValue @relation(fields: [rowValueId], references: [id], onDelete: Cascade) | |
} | |
// // TODO: MULTI SELECT | |
// model RowValueSelection { | |
// id String @id @default(cuid()) | |
// rowValueId String | |
// propertyOptionId String | |
// propertyOption PropertyOption @relation(fields: [propertyOptionId], references: [id], onDelete: Cascade) | |
// rowValue RowValue @relation(fields: [rowValueId], references: [id], onDelete: Cascade) | |
// } | |
model RowPermission { | |
id String @id @default(cuid()) | |
rowId String | |
tenantId String? | |
roleId String? | |
groupId String? | |
userId String? | |
public Boolean? | |
access String @default("view") | |
group Group? @relation(fields: [groupId], references: [id], onDelete: Cascade) | |
role Role? @relation(fields: [roleId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
user User? @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model RowMedia { | |
id String @id @default(cuid()) | |
rowValueId String | |
title String | |
name String | |
file String | |
type String | |
publicUrl String? | |
storageBucket String? | |
storageProvider String? | |
rowValue RowValue @relation(fields: [rowValueId], references: [id], onDelete: Cascade) | |
} | |
model RowTag { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
rowId String | |
tagId String | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
tag EntityTag @relation(fields: [tagId], references: [id], onDelete: Cascade) | |
} | |
model RowComment { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
rowId String | |
value String | |
isDeleted Boolean? | |
createdByUser User @relation(fields: [createdByUserId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
logs Log[] | |
reactions RowCommentReaction[] | |
} | |
model RowCommentReaction { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
rowCommentId String | |
reaction String | |
createdByUser User @relation(fields: [createdByUserId], references: [id], onDelete: Cascade) | |
rowComment RowComment @relation(fields: [rowCommentId], references: [id], onDelete: Cascade) | |
} | |
model RowTask { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
createdByUserId String | |
rowId String | |
title String | |
description String | |
completed Boolean | |
completedAt DateTime? | |
completedByUserId String? | |
assignedToUserId String? | |
deadline DateTime? | |
assignedToUser User? @relation("assignedToUser", fields: [assignedToUserId], references: [id], onDelete: Cascade) | |
completedByUser User? @relation("completedByUser", fields: [completedByUserId], references: [id], onDelete: Cascade) | |
createdByUser User @relation("createdByUser", fields: [createdByUserId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
} | |
model RowWorkflowTransition { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
byUserId String? | |
byApiKeyId String? | |
byEmailId String? | |
byEventWebhookAttemptId String? | |
rowId String | |
workflowStepId String | |
byUser User? @relation(fields: [byUserId], references: [id], onDelete: Cascade) | |
byApiKey ApiKey? @relation(fields: [byApiKeyId], references: [id], onDelete: Cascade) | |
byEmail Email? @relation(fields: [byEmailId], references: [id], onDelete: Cascade) | |
byEventWebhookAttempt EventWebhookAttempt? @relation(fields: [byEventWebhookAttemptId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
workflowStep EntityWorkflowStep @relation(fields: [workflowStepId], references: [id], onDelete: Cascade) | |
logs Log[] | |
} | |
// <--- END: Entities ---> | |
// <--- START: Inbound Emails ---> | |
model TenantInboundAddress { | |
id String @id @default(cuid()) | |
tenantId String | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
address String @unique | |
email Email[] | |
} | |
model Email { | |
id String @id @default(cuid()) | |
tenantInboundAddressId String? | |
tenantInboundAddress TenantInboundAddress? @relation(fields: [tenantInboundAddressId], references: [id], onDelete: Cascade) | |
messageId String @unique | |
type String // inbound, outbound | |
date DateTime | |
subject String | |
fromEmail String | |
fromName String? | |
toEmail String | |
toName String? | |
textBody String | |
htmlBody String | |
reads EmailRead[] | |
attachments EmailAttachment[] | |
cc EmailCc[] | |
transitions RowWorkflowTransition[] | |
} | |
model EmailRead { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
emailId String | |
email Email @relation(fields: [emailId], references: [id], onDelete: Cascade) | |
userId String | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
} | |
model EmailCc { | |
id String @id @default(cuid()) | |
emailId String | |
toEmail String | |
toName String? | |
email Email @relation(fields: [emailId], references: [id], onDelete: Cascade) | |
} | |
model EmailAttachment { | |
id String @id @default(cuid()) | |
emailId String | |
name String | |
type String | |
length Int | |
content String | |
publicUrl String? | |
storageBucket String? | |
storageProvider String? | |
email Email @relation(fields: [emailId], references: [id], onDelete: Cascade) | |
} | |
// <--- END: Inbound Emails ---> | |
// <--- START: Events ---> | |
model Event { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
tenantId String? | |
tenant Tenant? @relation(fields: [tenantId], references: [id]) | |
name String | |
data String | |
resource String? | |
attempts EventWebhookAttempt[] | |
} | |
model EventWebhookAttempt { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
startedAt DateTime? | |
finishedAt DateTime? | |
eventId String | |
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade) | |
endpoint String | |
success Boolean? | |
status Int? | |
message String? | |
body String? | |
transitions RowWorkflowTransition[] | |
} | |
// <--- END: Events ---> | |
// <!--- Analytics ---> | |
model AnalyticsSettings { | |
id String @id @default(cuid()) | |
public Boolean @default(false) | |
ignorePages String | |
onlyPages String | |
} | |
model AnalyticsUniqueVisitor { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
cookie String @unique | |
via String? | |
httpReferrer String? | |
browser String? | |
browserVersion String? | |
os String? | |
osVersion String? | |
device String? | |
source String? | |
medium String? | |
campaign String? | |
content String? | |
term String? | |
country String? | |
city String? | |
fromUrl String? | |
fromRoute String? | |
pageViews AnalyticsPageView[] | |
events AnalyticsEvent[] | |
} | |
model AnalyticsPageView { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
uniqueVisitorId String | |
uniqueVisitor AnalyticsUniqueVisitor @relation(fields: [uniqueVisitorId], references: [id], onDelete: Cascade) | |
url String | |
route String? | |
} | |
model AnalyticsEvent { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
uniqueVisitorId String | |
uniqueVisitor AnalyticsUniqueVisitor @relation(fields: [uniqueVisitorId], references: [id], onDelete: Cascade) | |
action String | |
category String? | |
label String? | |
value String? | |
url String? | |
route String? | |
featureFlagId String? | |
featureFlag FeatureFlag? @relation(fields: [featureFlagId], references: [id]) | |
} | |
// <!--- Email marketing ---> | |
model EmailSender { | |
id String @id @default(cuid()) | |
tenantId String? | |
provider String | |
stream String | |
apiKey String | |
fromEmail String | |
fromName String? | |
replyToEmail String? | |
tenant Tenant? @relation(fields: [tenantId], references: [id]) | |
campaigns Campaign[] | |
outboundEmails OutboundEmail[] | |
} | |
model Campaign { | |
id String @id @default(cuid()) | |
tenantId String? | |
emailSenderId String | |
name String | |
subject String | |
htmlBody String | |
textBody String? | |
status String @default("draft") | |
track Boolean | |
sentAt DateTime? | |
emailSender EmailSender @relation(fields: [emailSenderId], references: [id]) | |
recipients OutboundEmail[] | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
} | |
model OutboundEmail { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
tenantId String? | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
campaignId String? | |
campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: Cascade) | |
contactRowId String? | |
contactRow Row? @relation(fields: [contactRowId], references: [id]) | |
email String | |
fromSenderId String | |
isPreview Boolean? | |
error String? | |
sentAt DateTime? | |
deliveredAt DateTime? | |
bouncedAt DateTime? | |
spamComplainedAt DateTime? | |
unsubscribedAt DateTime? | |
fromSender EmailSender @relation(fields: [fromSenderId], references: [id]) | |
opens OutboundEmailOpen[] | |
clicks OutboundEmailClick[] | |
} | |
model OutboundEmailOpen { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
firstOpen Boolean | |
outboundEmailId String | |
outboundEmail OutboundEmail @relation(fields: [outboundEmailId], references: [id], onDelete: Cascade) | |
} | |
model OutboundEmailClick { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
link String | |
outboundEmailId String | |
outboundEmail OutboundEmail @relation(fields: [outboundEmailId], references: [id], onDelete: Cascade) | |
} | |
model Page { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
slug String | |
isPublished Boolean @default(false) | |
isPublic Boolean @default(false) | |
metaTags PageMetaTag[] | |
blocks PageBlock[] | |
} | |
model PageMetaTag { | |
id String @id @default(cuid()) | |
pageId String? | |
page Page? @relation(fields: [pageId], references: [id], onDelete: Cascade) | |
order Int? | |
name String | |
value String | |
@@unique([pageId, name, value]) | |
} | |
model PageBlock { | |
id String @id @default(cuid()) | |
pageId String | |
page Page @relation(fields: [pageId], references: [id]) | |
order Int | |
type String // hero, gallery, logoClouds, video... | |
value String | |
} | |
model Tag { | |
id String @id @default(cuid()) | |
name String @unique | |
color Int? | |
users TagUser[] | |
tenants TagTenant[] | |
} | |
model TagUser { | |
id String @id @default(cuid()) | |
userId String | |
user User @relation(fields: [userId], references: [id]) | |
tagId String | |
tag Tag @relation(fields: [tagId], references: [id]) | |
} | |
model TagTenant { | |
id String @id @default(cuid()) | |
tenantId String | |
tenant Tenant @relation(fields: [tenantId], references: [id]) | |
tagId String | |
tag Tag @relation(fields: [tagId], references: [id]) | |
} | |
model Onboarding { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
title String | |
type String // modal, page | |
realtime Boolean @default(false) | |
active Boolean @default(false) | |
canBeDismissed Boolean @default(true) | |
height String? | |
filters OnboardingFilter[] | |
steps OnboardingStep[] | |
sessions OnboardingSession[] | |
} | |
model OnboardingFilter { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
onboardingId String | |
onboarding Onboarding @relation(fields: [onboardingId], references: [id], onDelete: Cascade) | |
type String | |
value String? | |
matches OnboardingSessionFilterMatch[] | |
} | |
model OnboardingStep { | |
id String @id @default(cuid()) | |
onboardingId String | |
onboarding Onboarding @relation(fields: [onboardingId], references: [id], onDelete: Cascade) | |
order Int | |
block String | |
sessionSteps OnboardingSessionStep[] | |
} | |
model OnboardingSession { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
onboardingId String | |
onboarding Onboarding @relation(fields: [onboardingId], references: [id], onDelete: Cascade) | |
userId String | |
user User @relation(fields: [userId], references: [id], onDelete: Cascade) | |
tenantId String? | |
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
status String // active, completed, dismissed | |
startedAt DateTime? | |
completedAt DateTime? | |
dismissedAt DateTime? | |
createdRealtime Boolean @default(false) | |
matches OnboardingSessionFilterMatch[] | |
sessionSteps OnboardingSessionStep[] | |
actions OnboardingSessionAction[] | |
@@unique([onboardingId, userId, tenantId]) | |
} | |
model OnboardingSessionAction { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
onboardingSessionId String | |
onboardingSession OnboardingSession @relation(fields: [onboardingSessionId], references: [id], onDelete: Cascade) | |
type String | |
name String | |
value String | |
} | |
model OnboardingSessionFilterMatch { | |
id String @id @default(cuid()) | |
onboardingFilterId String | |
onboardingFilter OnboardingFilter @relation(fields: [onboardingFilterId], references: [id], onDelete: Cascade) | |
onboardingSessionId String | |
onboardingSession OnboardingSession @relation(fields: [onboardingSessionId], references: [id], onDelete: Cascade) | |
} | |
model OnboardingSessionStep { | |
id String @id @default(cuid()) | |
onboardingSessionId String | |
onboardingSession OnboardingSession @relation(fields: [onboardingSessionId], references: [id], onDelete: Cascade) | |
stepId String | |
step OnboardingStep @relation(fields: [stepId], references: [id], onDelete: Cascade) | |
seenAt DateTime? | |
completedAt DateTime? | |
} | |
model TenantIpAddress { | |
id String @id @default(cuid()) | |
tenantId String | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
userId String? | |
user User? @relation(fields: [userId], references: [id], onDelete: Cascade) | |
apiKeyId String? | |
apiKey ApiKey? @relation(fields: [apiKeyId], references: [id], onDelete: Cascade) | |
ip String | |
fromUrl String | |
createdAt DateTime @default(now()) | |
@@unique([tenantId, ip, userId, apiKeyId]) | |
} | |
model FeatureFlag { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
name String | |
description String | |
enabled Boolean @default(false) | |
events AnalyticsEvent[] | |
filters FeatureFlagFilter[] | |
@@unique([name, description]) | |
} | |
model FeatureFlagFilter { | |
id String @id @default(cuid()) | |
createdAt DateTime @default(now()) | |
featureFlagId String | |
featureFlag FeatureFlag @relation(fields: [featureFlagId], references: [id], onDelete: Cascade) | |
type String // [FeatureFlagsFilterType] percentage, darkMode, language.is, page.is, analytics.browser.is... | |
value String? // 0-100, true, false, en, de, fr, ... | |
} | |
model TenantSettingsRow { | |
tenantId String @unique | |
rowId String | |
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) | |
row Row @relation(fields: [rowId], references: [id], onDelete: Cascade) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment