Files
eventsphere/apps/api/prisma/schema.prisma
2026-04-25 21:57:48 +01:00

783 lines
23 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Tenant {
id String @id @default(cuid())
name String
slug String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
users User[]
roles Role[]
events Event[]
attendees Attendee[]
registrations Registration[]
invitees Invitee[]
rsvps RSVP[]
payments PaymentTransaction[]
settings TenantSetting?
integrations IntegrationSetting[]
eventPages EventPage[]
ticketTypes TicketType[]
forms Form[]
formSubmissions FormSubmission[]
qrCodes QRCode[]
checkIns CheckIn[]
communicationTemplates CommunicationTemplate[]
communicationLogs CommunicationLog[]
paystackWebhookEvents PaystackWebhookEvent[]
crmLeads CRMLead[]
crmDeals CRMDeal[]
crmActivities CRMActivity[]
workflows Workflow[]
workflowTriggers WorkflowTrigger[]
workflowActions WorkflowAction[]
calendarRoutingForms CalendarRoutingForm[]
calendarSlots CalendarSlot[]
bookings Booking[]
formFields FormField[]
}
model User {
id String @id @default(cuid())
tenantId String
email String
fullName String
phone String?
addressLine1 String?
addressLine2 String?
city String?
state String?
country String?
avatarUrl String?
mustChangePassword Boolean @default(false)
passwordHash String
refreshTokenId String? @unique
refreshTokenHash String?
refreshTokenExpiresAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
roles UserRole[]
performedCheckIns CheckIn[] @relation("CheckInUser")
crmActivities CRMActivity[] @relation("CRMActivityUser")
@@unique([tenantId, email])
@@index([tenantId])
}
model TenantSetting {
id String @id @default(cuid())
tenantId String @unique
appName String?
logoUrl String?
modules Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
}
model IntegrationSetting {
id String @id @default(cuid())
tenantId String
key String
value String?
isSecret Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
@@unique([tenantId, key])
@@index([tenantId])
}
model Role {
id String @id @default(cuid())
tenantId String
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
users UserRole[]
permissions RolePermission[]
@@unique([tenantId, name])
@@index([tenantId])
}
model Permission {
id String @id @default(cuid())
key String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
roles RolePermission[]
}
model UserRole {
id String @id @default(cuid())
userId String
roleId String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId])
}
model RolePermission {
id String @id @default(cuid())
roleId String
permissionId String
createdAt DateTime @default(now())
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
@@unique([roleId, permissionId])
}
enum EventStatus {
draft
active
closed
}
model Event {
id String @id @default(cuid())
tenantId String
name String
slug String
status EventStatus @default(draft)
startsAt DateTime
venue String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
attendees Attendee[]
registrations Registration[]
invitees Invitee[]
rsvps RSVP[]
payments PaymentTransaction[]
eventPage EventPage?
ticketTypes TicketType[]
forms Form[]
formSubmissions FormSubmission[]
checkIns CheckIn[]
crmLeads CRMLead[]
crmDeals CRMDeal[]
calendarRoutingForms CalendarRoutingForm[]
bookings Booking[]
@@unique([tenantId, slug])
@@index([tenantId])
@@index([tenantId, status])
}
enum RegistrationStatus {
pending
confirmed
cancelled
}
model Registration {
id String @id @default(cuid())
tenantId String
eventId String
attendeeId String
ticketTypeId String?
status RegistrationStatus @default(pending)
code String @unique
source String @default("admin")
checkedInAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
attendee Attendee @relation(fields: [attendeeId], references: [id], onDelete: Cascade)
ticketType TicketType? @relation(fields: [ticketTypeId], references: [id], onDelete: SetNull)
qrCode QRCode?
checkIns CheckIn[]
formSubmissions FormSubmission[]
communicationLogs CommunicationLog[]
payments PaymentTransaction[]
@@unique([tenantId, eventId, attendeeId])
@@index([tenantId])
@@index([tenantId, eventId])
@@index([eventId])
@@index([ticketTypeId])
}
enum InviteeStatus {
invited
delivered
opened
rsvped
bounced
}
model Invitee {
id String @id @default(cuid())
tenantId String
eventId String
fullName String
email String
phone String?
status InviteeStatus @default(invited)
code String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
rsvps RSVP[]
communicationLogs CommunicationLog[]
@@unique([tenantId, eventId, email])
@@index([tenantId])
@@index([tenantId, eventId])
}
enum RSVPResponse {
yes
no
maybe
}
model RSVP {
id String @id @default(cuid())
tenantId String
eventId String
inviteeId String?
response RSVPResponse
note String?
createdAt DateTime @default(now())
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
invitee Invitee? @relation(fields: [inviteeId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([tenantId, eventId])
@@index([inviteeId])
}
enum PaymentStatus {
initialized
success
failed
}
model PaymentTransaction {
id String @id @default(cuid())
tenantId String
eventId String
registrationId String?
ticketTypeId String?
email String
amountKobo Int
currency String @default("NGN")
provider String @default("paystack")
reference String @unique
status PaymentStatus @default(initialized)
raw Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
registration Registration? @relation(fields: [registrationId], references: [id], onDelete: SetNull)
ticketType TicketType? @relation(fields: [ticketTypeId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([tenantId, eventId])
@@index([eventId])
@@index([registrationId])
@@index([ticketTypeId])
}
model Attendee {
id String @id @default(cuid())
tenantId String
eventId String?
fullName String
email String
phone String?
tags String[] @default([])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
registrations Registration[]
formSubmissions FormSubmission[]
checkIns CheckIn[]
crmLeads CRMLead[]
bookings Booking[]
@@unique([tenantId, email])
@@index([tenantId])
@@index([tenantId, eventId])
}
model AuditLog {
id String @id @default(cuid())
tenantId String?
actorUserId String?
action String
entityType String?
entityId String?
ip String?
userAgent String?
metadata Json?
createdAt DateTime @default(now())
@@index([tenantId])
@@index([actorUserId])
@@index([entityType, entityId])
}
model EventPage {
id String @id @default(cuid())
tenantId String
eventId String @unique
title String
heroTitle String?
description String?
content Json?
theme Json?
publishedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
@@index([tenantId])
}
model TicketType {
id String @id @default(cuid())
tenantId String
eventId String
name String
description String?
priceKobo Int @default(0)
currency String @default("NGN")
capacity Int?
soldCount Int @default(0)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
registrations Registration[]
payments PaymentTransaction[]
@@unique([tenantId, eventId, name])
@@index([tenantId])
@@index([tenantId, eventId])
}
model Form {
id String @id @default(cuid())
tenantId String
eventId String?
name String
slug String
description String?
isPublic Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
fields FormField[]
submissions FormSubmission[]
@@unique([tenantId, slug])
@@index([tenantId])
@@index([tenantId, eventId])
}
model FormField {
id String @id @default(cuid())
tenantId String
formId String
label String
key String
type String
required Boolean @default(false)
options Json?
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)
@@unique([formId, key])
@@index([tenantId])
@@index([formId])
}
model FormSubmission {
id String @id @default(cuid())
tenantId String
formId String
eventId String?
attendeeId String?
registrationId String?
data Json
source String @default("admin")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
form Form @relation(fields: [formId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
attendee Attendee? @relation(fields: [attendeeId], references: [id], onDelete: SetNull)
registration Registration? @relation(fields: [registrationId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([formId])
@@index([eventId])
@@index([attendeeId])
@@index([registrationId])
}
model QRCode {
id String @id @default(cuid())
tenantId String
registrationId String @unique
code String @unique
payload Json
status QRCodeStatus @default(active)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
registration Registration @relation(fields: [registrationId], references: [id], onDelete: Cascade)
@@index([tenantId])
}
enum QRCodeStatus {
active
revoked
}
model CheckIn {
id String @id @default(cuid())
tenantId String
eventId String
registrationId String
attendeeId String?
checkedInByUserId String?
code String
result CheckInResult @default(checked_in)
note String?
createdAt DateTime @default(now())
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
registration Registration @relation(fields: [registrationId], references: [id], onDelete: Cascade)
attendee Attendee? @relation(fields: [attendeeId], references: [id], onDelete: SetNull)
checkedInBy User? @relation("CheckInUser", fields: [checkedInByUserId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([tenantId, eventId])
@@index([registrationId])
@@index([attendeeId])
}
enum CheckInResult {
checked_in
duplicate
rejected
}
model CommunicationTemplate {
id String @id @default(cuid())
tenantId String
name String
channel CommunicationChannel
subject String?
body String
variables Json?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
logs CommunicationLog[]
@@unique([tenantId, name, channel])
@@index([tenantId])
}
model CommunicationLog {
id String @id @default(cuid())
tenantId String
templateId String?
inviteeId String?
registrationId String?
channel CommunicationChannel
to String
subject String?
body String
status CommunicationStatus @default(queued)
providerMessageId String?
error String?
raw Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
template CommunicationTemplate? @relation(fields: [templateId], references: [id], onDelete: SetNull)
invitee Invitee? @relation(fields: [inviteeId], references: [id], onDelete: SetNull)
registration Registration? @relation(fields: [registrationId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([templateId])
@@index([inviteeId])
@@index([registrationId])
}
enum CommunicationChannel {
email
sms
whatsapp
}
enum CommunicationStatus {
queued
sent
failed
}
model PaystackWebhookEvent {
id String @id @default(cuid())
tenantId String?
event String
reference String?
status String @default("received")
raw Json
receivedAt DateTime @default(now())
processedAt DateTime?
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([reference])
}
model CRMLead {
id String @id @default(cuid())
tenantId String
eventId String?
attendeeId String?
fullName String
email String
phone String?
source String @default("manual")
status String @default("new")
valueKobo Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
attendee Attendee? @relation(fields: [attendeeId], references: [id], onDelete: SetNull)
deals CRMDeal[]
activities CRMActivity[]
@@unique([tenantId, email])
@@index([tenantId])
@@index([eventId])
@@index([attendeeId])
}
model CRMDeal {
id String @id @default(cuid())
tenantId String
leadId String?
eventId String?
title String
stage String @default("new")
valueKobo Int @default(0)
probability Int @default(0)
ownerUserId String?
expectedCloseAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
lead CRMLead? @relation(fields: [leadId], references: [id], onDelete: SetNull)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
activities CRMActivity[]
@@index([tenantId])
@@index([leadId])
@@index([eventId])
}
model CRMActivity {
id String @id @default(cuid())
tenantId String
leadId String?
dealId String?
userId String?
type String @default("note")
note String
dueAt DateTime?
completedAt DateTime?
createdAt DateTime @default(now())
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
lead CRMLead? @relation(fields: [leadId], references: [id], onDelete: SetNull)
deal CRMDeal? @relation(fields: [dealId], references: [id], onDelete: SetNull)
user User? @relation("CRMActivityUser", fields: [userId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([leadId])
@@index([dealId])
@@index([userId])
}
model Workflow {
id String @id @default(cuid())
tenantId String
name String
description String?
enabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
triggers WorkflowTrigger[]
actions WorkflowAction[]
@@unique([tenantId, name])
@@index([tenantId])
}
model WorkflowTrigger {
id String @id @default(cuid())
tenantId String
workflowId String
type String
config Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
@@index([tenantId])
@@index([workflowId])
}
model WorkflowAction {
id String @id @default(cuid())
tenantId String
workflowId String
type String
config Json?
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
@@index([tenantId])
@@index([workflowId])
}
model CalendarRoutingForm {
id String @id @default(cuid())
tenantId String
eventId String?
name String
slug String
description String?
durationMinutes Int @default(30)
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
slots CalendarSlot[]
bookings Booking[]
@@unique([tenantId, slug])
@@index([tenantId])
@@index([eventId])
}
model CalendarSlot {
id String @id @default(cuid())
tenantId String
routingFormId String
startsAt DateTime
endsAt DateTime
capacity Int @default(1)
bookedCount Int @default(0)
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
routingForm CalendarRoutingForm @relation(fields: [routingFormId], references: [id], onDelete: Cascade)
@@index([tenantId])
@@index([routingFormId])
@@index([startsAt])
}
model Booking {
id String @id @default(cuid())
tenantId String
routingFormId String
eventId String?
attendeeId String?
fullName String
email String
phone String?
startsAt DateTime
endsAt DateTime
status String @default("booked")
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
routingForm CalendarRoutingForm @relation(fields: [routingFormId], references: [id], onDelete: Cascade)
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
attendee Attendee? @relation(fields: [attendeeId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([routingFormId])
@@index([eventId])
@@index([attendeeId])
@@index([startsAt])
}