@danielcok17/prisma-db 1.18.0 → 1.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/prisma/app.prisma
CHANGED
|
@@ -30,113 +30,113 @@ model Account {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
model User {
|
|
33
|
-
id
|
|
34
|
-
brand
|
|
35
|
-
name
|
|
36
|
-
email
|
|
37
|
-
emailVerified
|
|
38
|
-
image
|
|
33
|
+
id String @id @default(cuid())
|
|
34
|
+
brand String @default("smartlex") // Multi-brand: "smartlex" | "justi"
|
|
35
|
+
name String?
|
|
36
|
+
email String?
|
|
37
|
+
emailVerified DateTime?
|
|
38
|
+
image String?
|
|
39
39
|
// Credentials authentication fields
|
|
40
|
-
password
|
|
41
|
-
createdAt
|
|
42
|
-
agreedToTerms
|
|
43
|
-
practiceArea
|
|
44
|
-
lawFirm
|
|
45
|
-
yearsOfExperience
|
|
40
|
+
password String? // Hashed password pre credentials login
|
|
41
|
+
createdAt DateTime @default(now())
|
|
42
|
+
agreedToTerms Boolean @default(false)
|
|
43
|
+
practiceArea String[]
|
|
44
|
+
lawFirm String?
|
|
45
|
+
yearsOfExperience Int?
|
|
46
46
|
// Nové polia pre schvalovanie používateľov
|
|
47
|
-
isApproved
|
|
48
|
-
isRejected
|
|
49
|
-
approvedAt
|
|
50
|
-
rejectedAt
|
|
51
|
-
approvedBy
|
|
52
|
-
rejectedBy
|
|
53
|
-
rejectionReason
|
|
47
|
+
isApproved Boolean @default(false) // Či je používateľ schválený
|
|
48
|
+
isRejected Boolean @default(false) // Či je používateľ zamietnutý
|
|
49
|
+
approvedAt DateTime? // Kedy bol schválený
|
|
50
|
+
rejectedAt DateTime? // Kedy bol zamietnutý
|
|
51
|
+
approvedBy String? // ID admina, ktorý schválil
|
|
52
|
+
rejectedBy String? // ID admina, ktorý zamietol
|
|
53
|
+
rejectionReason String? // Dôvod zamietnutia
|
|
54
54
|
// Nové polia pre tracking a žiadosť
|
|
55
|
-
referralSource
|
|
56
|
-
applicationText
|
|
55
|
+
referralSource String? // Odkiaľ sa o nás dozvedel (Google, Facebook, LinkedIn, etc.)
|
|
56
|
+
applicationText String? // Text žiadosti o prihlásenie
|
|
57
57
|
// ✨ STRIPE FIELDS (B2C - len pre individuálnych používateľov)
|
|
58
|
-
subscriptionTier
|
|
59
|
-
messageCount
|
|
60
|
-
messageCountResetAt
|
|
61
|
-
adminGrantExpiresAt
|
|
58
|
+
subscriptionTier SubscriptionTier @default(FREE) // Aktuálny subscription tier (cache)
|
|
59
|
+
messageCount Int @default(4) // Free tier default
|
|
60
|
+
messageCountResetAt DateTime? // Kedy sa má resetovať message count
|
|
61
|
+
adminGrantExpiresAt DateTime? // Kedy admin grant expiruje
|
|
62
62
|
// ✨ COMPANY FIELDS (pre SZČO - samostatne zárobkovo činná osoba)
|
|
63
|
-
customerType
|
|
64
|
-
companyName
|
|
65
|
-
companyNumber
|
|
66
|
-
vatNumber
|
|
67
|
-
taxNumber
|
|
68
|
-
companyStreet
|
|
69
|
-
companyCity
|
|
70
|
-
companyPostalCode
|
|
71
|
-
companyCountry
|
|
63
|
+
customerType CustomerType @default(INDIVIDUAL) // Typ zákazníka: fyzická osoba alebo SZČO
|
|
64
|
+
companyName String? // Obchodné meno (pre SZČO)
|
|
65
|
+
companyNumber String? // IČO (povinné pre SZČO, 8 číslic)
|
|
66
|
+
vatNumber String? // IČ DPH (SK + 10 číslic, nepovinné)
|
|
67
|
+
taxNumber String? // DIČ (10 číslic, nepovinné)
|
|
68
|
+
companyStreet String? // Ulica a číslo (pre SZČO)
|
|
69
|
+
companyCity String? // Mesto (pre SZČO)
|
|
70
|
+
companyPostalCode String? // PSČ (pre SZČO, formát: XXX XX)
|
|
71
|
+
companyCountry String? @default("SK") // Krajina (ISO kód, default SK)
|
|
72
72
|
// ✨ UTM TRACKING & ATTRIBUTION FIELDS
|
|
73
73
|
// First-visit attribution (celý lifecycle)
|
|
74
|
-
firstUtmSource
|
|
75
|
-
firstUtmMedium
|
|
76
|
-
firstUtmCampaign
|
|
77
|
-
firstUtmContent
|
|
78
|
-
firstUtmTerm
|
|
79
|
-
firstVisitAt
|
|
74
|
+
firstUtmSource String? // Prvý UTM source
|
|
75
|
+
firstUtmMedium String? // Prvý UTM medium
|
|
76
|
+
firstUtmCampaign String? // Prvá kampaň
|
|
77
|
+
firstUtmContent String? // Prvý content/variant
|
|
78
|
+
firstUtmTerm String? // Prvé keywords
|
|
79
|
+
firstVisitAt DateTime? // Kedy prvýkrát navštívil web
|
|
80
80
|
// Registration attribution
|
|
81
|
-
registrationUtmSource
|
|
82
|
-
registrationUtmMedium
|
|
83
|
-
registrationUtmCampaign
|
|
84
|
-
registrationUtmContent
|
|
85
|
-
registrationUtmTerm
|
|
81
|
+
registrationUtmSource String? // UTM source pri registrácii
|
|
82
|
+
registrationUtmMedium String? // UTM medium pri registrácii
|
|
83
|
+
registrationUtmCampaign String? // Kampaň pri registrácii
|
|
84
|
+
registrationUtmContent String? // Content/variant pri registrácii
|
|
85
|
+
registrationUtmTerm String? // Keywords pri registrácii
|
|
86
86
|
// Profile fields
|
|
87
|
-
phone
|
|
88
|
-
phoneVerified
|
|
89
|
-
occupation
|
|
90
|
-
preferredLanguage
|
|
87
|
+
phone String? // Mobilný telefón
|
|
88
|
+
phoneVerified DateTime? // Kedy bol telefón overený cez OTP
|
|
89
|
+
occupation String? // Povolanie (Právnik, Účtovník, etc.)
|
|
90
|
+
preferredLanguage String? @default("sk") // Jazyk odpovedi (sk, cs, en)
|
|
91
91
|
// Email Lifecycle — 360° user view
|
|
92
92
|
lastActiveAt DateTime?
|
|
93
93
|
lastLoginAt DateTime?
|
|
94
94
|
activatedAt DateTime?
|
|
95
|
-
lifecycleStage LifecycleStage
|
|
96
|
-
lifetimeValue Int
|
|
95
|
+
lifecycleStage LifecycleStage @default(REGISTERED)
|
|
96
|
+
lifetimeValue Int @default(0)
|
|
97
97
|
lastEmailSentAt DateTime?
|
|
98
98
|
lastMarketingEmailSentAt DateTime?
|
|
99
|
-
isEmailSuppressed Boolean
|
|
100
|
-
referralCode String?
|
|
101
|
-
churnRiskScore Int
|
|
99
|
+
isEmailSuppressed Boolean @default(false)
|
|
100
|
+
referralCode String? @unique
|
|
101
|
+
churnRiskScore Int @default(0)
|
|
102
102
|
churnRiskUpdatedAt DateTime?
|
|
103
103
|
// Relations
|
|
104
|
-
approvalRequest
|
|
105
|
-
stripeCustomer
|
|
106
|
-
ownedOrganizations
|
|
107
|
-
organizationMembers
|
|
108
|
-
createdInvites
|
|
109
|
-
accounts
|
|
110
|
-
answers
|
|
111
|
-
conversations
|
|
112
|
-
feedbacks
|
|
113
|
-
pageViews
|
|
114
|
-
sessions
|
|
115
|
-
workflowLogs
|
|
116
|
-
verificationTokens
|
|
117
|
-
passwordResetTokens
|
|
118
|
-
phoneOtps
|
|
119
|
-
canvasDocuments
|
|
120
|
-
canvasDocumentVersions
|
|
104
|
+
approvalRequest UserApprovalRequest?
|
|
105
|
+
stripeCustomer StripeCustomer? // ✨ B2C Stripe customer
|
|
106
|
+
ownedOrganizations Organization[] @relation("OrganizationOwner")
|
|
107
|
+
organizationMembers OrganizationMember[]
|
|
108
|
+
createdInvites OrganizationInvite[] @relation("InviteCreator")
|
|
109
|
+
accounts Account[]
|
|
110
|
+
answers Answer[]
|
|
111
|
+
conversations Conversation[]
|
|
112
|
+
feedbacks Feedback[]
|
|
113
|
+
pageViews PageView[]
|
|
114
|
+
sessions Session[]
|
|
115
|
+
workflowLogs WorkflowLog[]
|
|
116
|
+
verificationTokens VerificationToken[]
|
|
117
|
+
passwordResetTokens PasswordResetToken[]
|
|
118
|
+
phoneOtps PhoneOtp[]
|
|
119
|
+
canvasDocuments CanvasDocument[]
|
|
120
|
+
canvasDocumentVersions CanvasDocumentVersion[]
|
|
121
121
|
// Folder system relations
|
|
122
|
-
ownedFolders
|
|
123
|
-
addedFolderItems
|
|
124
|
-
folderActivities
|
|
125
|
-
folderSharesReceived
|
|
126
|
-
createdFolderShares
|
|
122
|
+
ownedFolders Folder[] @relation("FolderOwner")
|
|
123
|
+
addedFolderItems FolderItem[] @relation("FolderItemAdder")
|
|
124
|
+
folderActivities FolderActivity[] @relation("FolderActivityUser")
|
|
125
|
+
folderSharesReceived FolderShare[] @relation("FolderShareUser")
|
|
126
|
+
createdFolderShares FolderShare[] @relation("FolderShareCreator")
|
|
127
127
|
// UTM tracking relations
|
|
128
|
-
touchPoints
|
|
129
|
-
conversions
|
|
128
|
+
touchPoints TouchPoint[]
|
|
129
|
+
conversions Conversion[]
|
|
130
130
|
// Ingestion pipeline
|
|
131
|
-
ingestedDocuments
|
|
132
|
-
adminGrants
|
|
133
|
-
invoiceGrants
|
|
134
|
-
emailSends
|
|
135
|
-
emailConsent
|
|
136
|
-
userScore
|
|
137
|
-
sequenceEnrollments
|
|
138
|
-
referralsSent
|
|
139
|
-
referralsReceived
|
|
131
|
+
ingestedDocuments IngestedDocument[]
|
|
132
|
+
adminGrants AdminGrant[]
|
|
133
|
+
invoiceGrants InvoiceGrant[]
|
|
134
|
+
emailSends EmailSend[]
|
|
135
|
+
emailConsent EmailConsent?
|
|
136
|
+
userScore UserScore?
|
|
137
|
+
sequenceEnrollments EmailSequenceEnrollment[]
|
|
138
|
+
referralsSent Referral[] @relation("ReferralsSent")
|
|
139
|
+
referralsReceived Referral[] @relation("ReferralsReceived")
|
|
140
140
|
|
|
141
141
|
// Multi-brand: compound unique allows same email across brands
|
|
142
142
|
@@unique([email, brand])
|
|
@@ -197,10 +197,10 @@ model Organization {
|
|
|
197
197
|
|
|
198
198
|
// Subscription (B2B)
|
|
199
199
|
subscriptionTier SubscriptionTier @default(FREE) // Tier organizácie (cache)
|
|
200
|
-
messageCount Int @default(0)
|
|
201
|
-
messageLimit Int @default(4)
|
|
202
|
-
messageCountResetAt DateTime?
|
|
203
|
-
adminGrantExpiresAt DateTime?
|
|
200
|
+
messageCount Int @default(0) // Spoločný pool správ pre všetkých členov
|
|
201
|
+
messageLimit Int @default(4) // Free tier default
|
|
202
|
+
messageCountResetAt DateTime? // Kedy sa má resetovať pool
|
|
203
|
+
adminGrantExpiresAt DateTime? // Kedy admin grant expiruje
|
|
204
204
|
|
|
205
205
|
// Settings
|
|
206
206
|
isActive Boolean @default(true)
|
|
@@ -287,7 +287,7 @@ model Conversation {
|
|
|
287
287
|
updatedAt DateTime @updatedAt
|
|
288
288
|
summary String?
|
|
289
289
|
messagesSinceLastSummary Int? @default(0)
|
|
290
|
-
integrityHash String?
|
|
290
|
+
integrityHash String? // HMAC-SHA256 hash chain - posledný chainHash pre verifikáciu integrity
|
|
291
291
|
// Relácie
|
|
292
292
|
answers Answer[]
|
|
293
293
|
user User @relation(fields: [userId], references: [id])
|
|
@@ -312,8 +312,8 @@ model Answer {
|
|
|
312
312
|
processingTime Int?
|
|
313
313
|
model String?
|
|
314
314
|
userId String?
|
|
315
|
-
contentHash String?
|
|
316
|
-
chainHash String?
|
|
315
|
+
contentHash String? // HMAC-SHA256 hash obsahu správy (content + role + messageId)
|
|
316
|
+
chainHash String? // Hash chain - zahŕňa predchádzajúci chainHash pre integritu sekvencie
|
|
317
317
|
createdAt DateTime @default(now())
|
|
318
318
|
updatedAt DateTime @updatedAt
|
|
319
319
|
// Relácie
|
|
@@ -334,13 +334,13 @@ model Answer {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
model MessageFile {
|
|
337
|
-
id
|
|
338
|
-
answerId
|
|
339
|
-
fileName
|
|
340
|
-
fileType
|
|
341
|
-
base64Data
|
|
342
|
-
uploadedAt
|
|
343
|
-
answer
|
|
337
|
+
id String @id @default(cuid())
|
|
338
|
+
answerId String?
|
|
339
|
+
fileName String
|
|
340
|
+
fileType String
|
|
341
|
+
base64Data String
|
|
342
|
+
uploadedAt DateTime @default(now())
|
|
343
|
+
answer Answer? @relation(fields: [answerId], references: [id], onDelete: Cascade)
|
|
344
344
|
|
|
345
345
|
@@index([answerId])
|
|
346
346
|
@@index([fileType])
|
|
@@ -847,11 +847,11 @@ enum CustomerType {
|
|
|
847
847
|
|
|
848
848
|
// Stripe: Tier predplatného
|
|
849
849
|
enum SubscriptionTier {
|
|
850
|
-
FREE
|
|
851
|
-
LAWYER
|
|
852
|
-
LAWYER_PRO
|
|
853
|
-
LAW_FIRM
|
|
854
|
-
ENTERPRISE
|
|
850
|
+
FREE // Free tier (4 messages/month)
|
|
851
|
+
LAWYER // Lawyer tier (1000 messages/month, €29/month, 1 user)
|
|
852
|
+
LAWYER_PRO // Lawyer Pro tier (3000 messages/month, €49/month, 1 user) - RECOMMENDED
|
|
853
|
+
LAW_FIRM // Law Firm tier (10000 messages/month, €129/month, up to 5 users)
|
|
854
|
+
ENTERPRISE // Enterprise tier (unlimited messages, unlimited users, custom pricing)
|
|
855
855
|
}
|
|
856
856
|
|
|
857
857
|
// Stripe: Billing interval
|
|
@@ -1033,19 +1033,81 @@ model PasswordResetToken {
|
|
|
1033
1033
|
|
|
1034
1034
|
// Phone OTP verification (BulkGate)
|
|
1035
1035
|
model PhoneOtp {
|
|
1036
|
-
id
|
|
1037
|
-
userId
|
|
1038
|
-
phone
|
|
1039
|
-
bulkgateId
|
|
1040
|
-
expiresAt
|
|
1041
|
-
createdAt
|
|
1042
|
-
user
|
|
1036
|
+
id String @id @default(cuid())
|
|
1037
|
+
userId String
|
|
1038
|
+
phone String
|
|
1039
|
+
bulkgateId String @unique // OTP ID from BulkGate API response
|
|
1040
|
+
expiresAt DateTime
|
|
1041
|
+
createdAt DateTime @default(now())
|
|
1042
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1043
1043
|
|
|
1044
1044
|
@@index([userId])
|
|
1045
1045
|
@@index([bulkgateId])
|
|
1046
1046
|
@@index([expiresAt])
|
|
1047
1047
|
}
|
|
1048
1048
|
|
|
1049
|
+
model MeetingSlot {
|
|
1050
|
+
id String @id @default(cuid())
|
|
1051
|
+
startsAt DateTime
|
|
1052
|
+
durationMinutes Int @default(30)
|
|
1053
|
+
status MeetingSlotStatus @default(AVAILABLE)
|
|
1054
|
+
holdExpiresAt DateTime?
|
|
1055
|
+
note String?
|
|
1056
|
+
createdByAdminEmail String?
|
|
1057
|
+
createdAt DateTime @default(now())
|
|
1058
|
+
updatedAt DateTime @updatedAt
|
|
1059
|
+
|
|
1060
|
+
bookings MeetingBooking[]
|
|
1061
|
+
|
|
1062
|
+
@@index([status, startsAt])
|
|
1063
|
+
@@index([startsAt])
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
model MeetingBooking {
|
|
1067
|
+
id String @id @default(cuid())
|
|
1068
|
+
slotId String
|
|
1069
|
+
status MeetingBookingStatus @default(OTP_PENDING)
|
|
1070
|
+
name String?
|
|
1071
|
+
email String
|
|
1072
|
+
phone String
|
|
1073
|
+
visitorNote String?
|
|
1074
|
+
publicToken String @unique
|
|
1075
|
+
bulkgateId String? @unique
|
|
1076
|
+
otpExpiresAt DateTime?
|
|
1077
|
+
holdExpiresAt DateTime?
|
|
1078
|
+
phoneVerifiedAt DateTime?
|
|
1079
|
+
slotStartAt DateTime
|
|
1080
|
+
slotEndAt DateTime
|
|
1081
|
+
adminNote String?
|
|
1082
|
+
adminActionBy String?
|
|
1083
|
+
acceptedAt DateTime?
|
|
1084
|
+
declinedAt DateTime?
|
|
1085
|
+
canceledAt DateTime?
|
|
1086
|
+
completedAt DateTime?
|
|
1087
|
+
noShowAt DateTime?
|
|
1088
|
+
createdAt DateTime @default(now())
|
|
1089
|
+
updatedAt DateTime @updatedAt
|
|
1090
|
+
|
|
1091
|
+
slot MeetingSlot @relation(fields: [slotId], references: [id], onDelete: Cascade)
|
|
1092
|
+
|
|
1093
|
+
@@index([slotId])
|
|
1094
|
+
@@index([status, createdAt])
|
|
1095
|
+
@@index([email])
|
|
1096
|
+
@@index([phone])
|
|
1097
|
+
@@index([slotStartAt])
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
model MeetingBookingSettings {
|
|
1101
|
+
id String @id @default("default")
|
|
1102
|
+
bookingEnabled Boolean @default(true)
|
|
1103
|
+
timezone String @default("Europe/Bratislava")
|
|
1104
|
+
bookingHorizonDays Int @default(30)
|
|
1105
|
+
minLeadHours Int @default(12)
|
|
1106
|
+
adminNotificationEmail String @default("info@smartlex.sk")
|
|
1107
|
+
createdAt DateTime @default(now())
|
|
1108
|
+
updatedAt DateTime @updatedAt
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1049
1111
|
// ============================================
|
|
1050
1112
|
// INGESTION PIPELINE MODELS
|
|
1051
1113
|
// ============================================
|
|
@@ -1065,7 +1127,7 @@ model IngestedDocument {
|
|
|
1065
1127
|
references String[] // Legal references from classification
|
|
1066
1128
|
chunkCount Int?
|
|
1067
1129
|
embeddingCost Float? // EUR
|
|
1068
|
-
qdrantDocId String?
|
|
1130
|
+
qdrantDocId String? @unique // doc_id used in Qdrant vector payloads
|
|
1069
1131
|
folderId String? // Optional folder association
|
|
1070
1132
|
storagePath String? // Local filesystem path (dev/staging)
|
|
1071
1133
|
storageUrl String? // Cloud storage URL (prod — S3/DigitalOcean Spaces)
|
|
@@ -1154,14 +1216,33 @@ enum ReferralStatus {
|
|
|
1154
1216
|
}
|
|
1155
1217
|
|
|
1156
1218
|
enum InvoiceGrantStatus {
|
|
1157
|
-
PENDING
|
|
1158
|
-
PAID
|
|
1159
|
-
VOID
|
|
1219
|
+
PENDING // Faktúra odoslaná, čaká na platbu
|
|
1220
|
+
PAID // Zaplatené, grant aktívny
|
|
1221
|
+
VOID // Stornovaná (admin alebo Stripe)
|
|
1160
1222
|
}
|
|
1161
1223
|
|
|
1162
1224
|
enum CollectionMethod {
|
|
1163
1225
|
CHARGE_AUTOMATICALLY // Automatické strhnutie kartou
|
|
1164
|
-
SEND_INVOICE
|
|
1226
|
+
SEND_INVOICE // Faktúra na email (bank transfer)
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
enum MeetingSlotStatus {
|
|
1230
|
+
AVAILABLE
|
|
1231
|
+
HELD
|
|
1232
|
+
BOOKED
|
|
1233
|
+
BLOCKED
|
|
1234
|
+
ARCHIVED
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
enum MeetingBookingStatus {
|
|
1238
|
+
OTP_PENDING
|
|
1239
|
+
PENDING_ADMIN_REVIEW
|
|
1240
|
+
ACCEPTED
|
|
1241
|
+
DECLINED
|
|
1242
|
+
CANCELED
|
|
1243
|
+
COMPLETED
|
|
1244
|
+
NO_SHOW
|
|
1245
|
+
EXPIRED
|
|
1165
1246
|
}
|
|
1166
1247
|
|
|
1167
1248
|
// ============================================
|
|
@@ -1389,20 +1470,20 @@ model AdminGrant {
|
|
|
1389
1470
|
// One-off admin invoice — standalone faktúra pre špeciálne prípady (demo, trial, custom deal)
|
|
1390
1471
|
// Pre recurring fakturáciu použiť StripeSubscription s collectionMethod=SEND_INVOICE
|
|
1391
1472
|
model InvoiceGrant {
|
|
1392
|
-
id
|
|
1393
|
-
userId
|
|
1394
|
-
organizationId
|
|
1395
|
-
stripeInvoiceId
|
|
1396
|
-
tier
|
|
1397
|
-
durationDays
|
|
1398
|
-
amount
|
|
1399
|
-
status
|
|
1400
|
-
grantId
|
|
1401
|
-
createdBy
|
|
1402
|
-
notes
|
|
1403
|
-
paidAt
|
|
1404
|
-
createdAt
|
|
1405
|
-
updatedAt
|
|
1473
|
+
id String @id @default(cuid())
|
|
1474
|
+
userId String?
|
|
1475
|
+
organizationId String?
|
|
1476
|
+
stripeInvoiceId String @unique
|
|
1477
|
+
tier SubscriptionTier
|
|
1478
|
+
durationDays Int // Na koľko dní sa aktivuje grant po platbe
|
|
1479
|
+
amount Int // Suma v centoch (EUR)
|
|
1480
|
+
status InvoiceGrantStatus @default(PENDING)
|
|
1481
|
+
grantId String? // ID AdminGrantu vytvoreného po platbe
|
|
1482
|
+
createdBy String // Admin email
|
|
1483
|
+
notes String?
|
|
1484
|
+
paidAt DateTime?
|
|
1485
|
+
createdAt DateTime @default(now())
|
|
1486
|
+
updatedAt DateTime @updatedAt
|
|
1406
1487
|
|
|
1407
1488
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1408
1489
|
organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
@@ -1440,39 +1521,39 @@ model AppInvite {
|
|
|
1440
1521
|
// ============================================
|
|
1441
1522
|
|
|
1442
1523
|
model EmailSend {
|
|
1443
|
-
id
|
|
1444
|
-
userId
|
|
1445
|
-
templateSlug
|
|
1446
|
-
campaignId
|
|
1447
|
-
|
|
1448
|
-
status
|
|
1449
|
-
sentAt
|
|
1450
|
-
deliveredAt
|
|
1451
|
-
toEmail
|
|
1452
|
-
fromEmail
|
|
1524
|
+
id String @id @default(cuid())
|
|
1525
|
+
userId String?
|
|
1526
|
+
templateSlug String
|
|
1527
|
+
campaignId String?
|
|
1528
|
+
|
|
1529
|
+
status EmailStatus @default(QUEUED)
|
|
1530
|
+
sentAt DateTime?
|
|
1531
|
+
deliveredAt DateTime?
|
|
1532
|
+
toEmail String
|
|
1533
|
+
fromEmail String @default("info@mail.smartlex.sk")
|
|
1534
|
+
|
|
1535
|
+
openedAt DateTime?
|
|
1536
|
+
openCount Int @default(0)
|
|
1537
|
+
clickedAt DateTime?
|
|
1538
|
+
clickCount Int @default(0)
|
|
1539
|
+
|
|
1540
|
+
bouncedAt DateTime?
|
|
1541
|
+
bounceType BounceType?
|
|
1542
|
+
complainedAt DateTime?
|
|
1543
|
+
unsubscribedAt DateTime?
|
|
1544
|
+
|
|
1545
|
+
errorMessage String?
|
|
1546
|
+
errorCode String?
|
|
1547
|
+
|
|
1548
|
+
subjectLine String?
|
|
1549
|
+
espMessageId String? @unique
|
|
1550
|
+
idempotencyKey String? @unique
|
|
1551
|
+
isTransactional Boolean @default(false)
|
|
1552
|
+
metadata Json?
|
|
1453
1553
|
|
|
1454
|
-
|
|
1455
|
-
openCount Int @default(0)
|
|
1456
|
-
clickedAt DateTime?
|
|
1457
|
-
clickCount Int @default(0)
|
|
1458
|
-
|
|
1459
|
-
bouncedAt DateTime?
|
|
1460
|
-
bounceType BounceType?
|
|
1461
|
-
complainedAt DateTime?
|
|
1462
|
-
unsubscribedAt DateTime?
|
|
1463
|
-
|
|
1464
|
-
errorMessage String?
|
|
1465
|
-
errorCode String?
|
|
1466
|
-
|
|
1467
|
-
subjectLine String?
|
|
1468
|
-
espMessageId String? @unique
|
|
1469
|
-
idempotencyKey String? @unique
|
|
1470
|
-
isTransactional Boolean @default(false)
|
|
1471
|
-
metadata Json?
|
|
1472
|
-
|
|
1473
|
-
createdAt DateTime @default(now())
|
|
1554
|
+
createdAt DateTime @default(now())
|
|
1474
1555
|
|
|
1475
|
-
user
|
|
1556
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
1476
1557
|
|
|
1477
1558
|
@@index([userId])
|
|
1478
1559
|
@@index([templateSlug])
|
|
@@ -1486,43 +1567,43 @@ model EmailSend {
|
|
|
1486
1567
|
}
|
|
1487
1568
|
|
|
1488
1569
|
model EmailSequence {
|
|
1489
|
-
id
|
|
1490
|
-
slug
|
|
1491
|
-
name
|
|
1492
|
-
description
|
|
1493
|
-
triggerEvent
|
|
1494
|
-
isActive
|
|
1570
|
+
id String @id @default(cuid())
|
|
1571
|
+
slug String @unique
|
|
1572
|
+
name String
|
|
1573
|
+
description String?
|
|
1574
|
+
triggerEvent String
|
|
1575
|
+
isActive Boolean @default(true)
|
|
1495
1576
|
|
|
1496
|
-
steps
|
|
1497
|
-
enrollments
|
|
1577
|
+
steps EmailSequenceStep[]
|
|
1578
|
+
enrollments EmailSequenceEnrollment[]
|
|
1498
1579
|
|
|
1499
|
-
createdAt
|
|
1500
|
-
updatedAt
|
|
1580
|
+
createdAt DateTime @default(now())
|
|
1581
|
+
updatedAt DateTime @updatedAt
|
|
1501
1582
|
}
|
|
1502
1583
|
|
|
1503
1584
|
model EmailSequenceStep {
|
|
1504
|
-
id String
|
|
1585
|
+
id String @id @default(cuid())
|
|
1505
1586
|
sequenceId String
|
|
1506
1587
|
templateSlug String
|
|
1507
1588
|
stepOrder Int
|
|
1508
|
-
delayMinutes Int
|
|
1589
|
+
delayMinutes Int @default(0)
|
|
1509
1590
|
sendCondition Json?
|
|
1510
1591
|
skipCondition Json?
|
|
1511
|
-
isActive Boolean
|
|
1592
|
+
isActive Boolean @default(true)
|
|
1512
1593
|
|
|
1513
|
-
sequence
|
|
1594
|
+
sequence EmailSequence @relation(fields: [sequenceId], references: [id], onDelete: Cascade)
|
|
1514
1595
|
|
|
1515
|
-
createdAt
|
|
1596
|
+
createdAt DateTime @default(now())
|
|
1516
1597
|
|
|
1517
1598
|
@@unique([sequenceId, stepOrder])
|
|
1518
1599
|
}
|
|
1519
1600
|
|
|
1520
1601
|
model EmailSequenceEnrollment {
|
|
1521
|
-
id
|
|
1522
|
-
userId
|
|
1523
|
-
sequenceId
|
|
1524
|
-
currentStep
|
|
1525
|
-
status
|
|
1602
|
+
id String @id @default(cuid())
|
|
1603
|
+
userId String
|
|
1604
|
+
sequenceId String
|
|
1605
|
+
currentStep Int @default(0)
|
|
1606
|
+
status EnrollmentStatus @default(ACTIVE)
|
|
1526
1607
|
|
|
1527
1608
|
enrolledAt DateTime @default(now())
|
|
1528
1609
|
completedAt DateTime?
|
|
@@ -1531,51 +1612,51 @@ model EmailSequenceEnrollment {
|
|
|
1531
1612
|
nextSendAt DateTime?
|
|
1532
1613
|
processingLockedAt DateTime?
|
|
1533
1614
|
|
|
1534
|
-
user
|
|
1535
|
-
sequence
|
|
1615
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1616
|
+
sequence EmailSequence @relation(fields: [sequenceId], references: [id])
|
|
1536
1617
|
|
|
1537
1618
|
@@index([status, nextSendAt])
|
|
1538
1619
|
@@index([userId, sequenceId, status])
|
|
1539
1620
|
}
|
|
1540
1621
|
|
|
1541
1622
|
model EmailConsent {
|
|
1542
|
-
id
|
|
1543
|
-
userId
|
|
1623
|
+
id String @id @default(cuid())
|
|
1624
|
+
userId String @unique
|
|
1544
1625
|
|
|
1545
|
-
marketingConsent
|
|
1546
|
-
productUpdatesConsent
|
|
1547
|
-
legalNewsConsent
|
|
1626
|
+
marketingConsent Boolean @default(false)
|
|
1627
|
+
productUpdatesConsent Boolean @default(false)
|
|
1628
|
+
legalNewsConsent Boolean @default(false)
|
|
1548
1629
|
|
|
1549
|
-
doubleOptinSentAt
|
|
1550
|
-
doubleOptinConfirmedAt
|
|
1551
|
-
doubleOptinToken
|
|
1630
|
+
doubleOptinSentAt DateTime?
|
|
1631
|
+
doubleOptinConfirmedAt DateTime?
|
|
1632
|
+
doubleOptinToken String? @unique
|
|
1552
1633
|
|
|
1553
|
-
user
|
|
1554
|
-
history
|
|
1634
|
+
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
|
|
1635
|
+
history EmailConsentHistory[]
|
|
1555
1636
|
|
|
1556
|
-
createdAt
|
|
1557
|
-
updatedAt
|
|
1637
|
+
createdAt DateTime @default(now())
|
|
1638
|
+
updatedAt DateTime @updatedAt
|
|
1558
1639
|
}
|
|
1559
1640
|
|
|
1560
1641
|
model EmailConsentHistory {
|
|
1561
|
-
id
|
|
1562
|
-
consentId
|
|
1563
|
-
userId
|
|
1642
|
+
id String @id @default(cuid())
|
|
1643
|
+
consentId String
|
|
1644
|
+
userId String
|
|
1564
1645
|
|
|
1565
|
-
action
|
|
1566
|
-
channel
|
|
1567
|
-
oldValue
|
|
1568
|
-
newValue
|
|
1646
|
+
action ConsentAction
|
|
1647
|
+
channel String
|
|
1648
|
+
oldValue Boolean?
|
|
1649
|
+
newValue Boolean
|
|
1569
1650
|
|
|
1570
|
-
consentText
|
|
1571
|
-
consentVersion
|
|
1572
|
-
consentMethod
|
|
1573
|
-
ipAddress
|
|
1574
|
-
userAgent
|
|
1651
|
+
consentText String
|
|
1652
|
+
consentVersion String
|
|
1653
|
+
consentMethod String
|
|
1654
|
+
ipAddress String?
|
|
1655
|
+
userAgent String?
|
|
1575
1656
|
|
|
1576
|
-
consent
|
|
1657
|
+
consent EmailConsent @relation(fields: [consentId], references: [id], onDelete: Restrict)
|
|
1577
1658
|
|
|
1578
|
-
createdAt
|
|
1659
|
+
createdAt DateTime @default(now())
|
|
1579
1660
|
|
|
1580
1661
|
@@index([userId, createdAt])
|
|
1581
1662
|
@@index([consentId])
|
|
@@ -1583,25 +1664,25 @@ model EmailConsentHistory {
|
|
|
1583
1664
|
}
|
|
1584
1665
|
|
|
1585
1666
|
model UserScore {
|
|
1586
|
-
id
|
|
1587
|
-
userId
|
|
1588
|
-
score
|
|
1589
|
-
leadSegment
|
|
1590
|
-
churnRisk
|
|
1667
|
+
id String @id @default(cuid())
|
|
1668
|
+
userId String @unique
|
|
1669
|
+
score Int @default(0)
|
|
1670
|
+
leadSegment LeadSegment @default(COLD)
|
|
1671
|
+
churnRisk ChurnRisk @default(NONE)
|
|
1591
1672
|
|
|
1592
|
-
signupScore Int
|
|
1593
|
-
engagementScore Int
|
|
1594
|
-
usageScore Int
|
|
1595
|
-
intentScore Int
|
|
1596
|
-
decayScore Int
|
|
1673
|
+
signupScore Int @default(0)
|
|
1674
|
+
engagementScore Int @default(0)
|
|
1675
|
+
usageScore Int @default(0)
|
|
1676
|
+
intentScore Int @default(0)
|
|
1677
|
+
decayScore Int @default(0)
|
|
1597
1678
|
|
|
1598
|
-
lastActivityAt
|
|
1599
|
-
scoreUpdatedAt
|
|
1679
|
+
lastActivityAt DateTime?
|
|
1680
|
+
scoreUpdatedAt DateTime @default(now())
|
|
1600
1681
|
|
|
1601
|
-
user
|
|
1602
|
-
events
|
|
1682
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1683
|
+
events UserScoreEvent[]
|
|
1603
1684
|
|
|
1604
|
-
createdAt
|
|
1685
|
+
createdAt DateTime @default(now())
|
|
1605
1686
|
|
|
1606
1687
|
@@index([score])
|
|
1607
1688
|
@@index([leadSegment])
|
|
@@ -1609,18 +1690,18 @@ model UserScore {
|
|
|
1609
1690
|
}
|
|
1610
1691
|
|
|
1611
1692
|
model UserScoreEvent {
|
|
1612
|
-
id
|
|
1613
|
-
userScoreId
|
|
1614
|
-
userId
|
|
1615
|
-
eventType
|
|
1616
|
-
pointsDelta
|
|
1617
|
-
scoreBefore
|
|
1618
|
-
scoreAfter
|
|
1619
|
-
metadata
|
|
1693
|
+
id String @id @default(cuid())
|
|
1694
|
+
userScoreId String
|
|
1695
|
+
userId String
|
|
1696
|
+
eventType String
|
|
1697
|
+
pointsDelta Int
|
|
1698
|
+
scoreBefore Int
|
|
1699
|
+
scoreAfter Int
|
|
1700
|
+
metadata Json?
|
|
1620
1701
|
|
|
1621
|
-
userScore
|
|
1702
|
+
userScore UserScore @relation(fields: [userScoreId], references: [id], onDelete: Cascade)
|
|
1622
1703
|
|
|
1623
|
-
createdAt
|
|
1704
|
+
createdAt DateTime @default(now())
|
|
1624
1705
|
|
|
1625
1706
|
@@index([userId, createdAt])
|
|
1626
1707
|
@@index([userScoreId])
|
|
@@ -1629,35 +1710,35 @@ model UserScoreEvent {
|
|
|
1629
1710
|
}
|
|
1630
1711
|
|
|
1631
1712
|
model EmailSuppression {
|
|
1632
|
-
id
|
|
1633
|
-
email
|
|
1634
|
-
reason
|
|
1635
|
-
source
|
|
1713
|
+
id String @id @default(cuid())
|
|
1714
|
+
email String
|
|
1715
|
+
reason SuppressionReason
|
|
1716
|
+
source String?
|
|
1636
1717
|
|
|
1637
|
-
suppressedAt
|
|
1718
|
+
suppressedAt DateTime @default(now())
|
|
1638
1719
|
|
|
1639
1720
|
@@unique([email, reason])
|
|
1640
1721
|
@@index([email])
|
|
1641
1722
|
}
|
|
1642
1723
|
|
|
1643
1724
|
model Referral {
|
|
1644
|
-
id
|
|
1645
|
-
referrerId
|
|
1646
|
-
referredUserId
|
|
1647
|
-
referredEmail
|
|
1648
|
-
status
|
|
1649
|
-
referralCode
|
|
1650
|
-
|
|
1651
|
-
rewardType
|
|
1652
|
-
rewardedAt
|
|
1653
|
-
clickCount
|
|
1654
|
-
registeredAt
|
|
1655
|
-
convertedAt
|
|
1656
|
-
|
|
1657
|
-
createdAt
|
|
1658
|
-
|
|
1659
|
-
referrer
|
|
1660
|
-
referredUser
|
|
1725
|
+
id String @id @default(cuid())
|
|
1726
|
+
referrerId String?
|
|
1727
|
+
referredUserId String?
|
|
1728
|
+
referredEmail String?
|
|
1729
|
+
status ReferralStatus @default(PENDING)
|
|
1730
|
+
referralCode String @unique
|
|
1731
|
+
|
|
1732
|
+
rewardType String?
|
|
1733
|
+
rewardedAt DateTime?
|
|
1734
|
+
clickCount Int @default(0)
|
|
1735
|
+
registeredAt DateTime?
|
|
1736
|
+
convertedAt DateTime?
|
|
1737
|
+
|
|
1738
|
+
createdAt DateTime @default(now())
|
|
1739
|
+
|
|
1740
|
+
referrer User? @relation("ReferralsSent", fields: [referrerId], references: [id], onDelete: SetNull)
|
|
1741
|
+
referredUser User? @relation("ReferralsReceived", fields: [referredUserId], references: [id], onDelete: SetNull)
|
|
1661
1742
|
|
|
1662
1743
|
@@index([referrerId])
|
|
1663
1744
|
@@index([referredUserId])
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
-- CreateEnum
|
|
2
|
+
CREATE TYPE "MeetingSlotStatus" AS ENUM ('AVAILABLE', 'HELD', 'BOOKED', 'BLOCKED', 'ARCHIVED');
|
|
3
|
+
|
|
4
|
+
-- CreateEnum
|
|
5
|
+
CREATE TYPE "MeetingBookingStatus" AS ENUM ('OTP_PENDING', 'PENDING_ADMIN_REVIEW', 'ACCEPTED', 'DECLINED', 'CANCELED', 'COMPLETED', 'NO_SHOW', 'EXPIRED');
|
|
6
|
+
|
|
7
|
+
-- CreateTable
|
|
8
|
+
CREATE TABLE "MeetingSlot" (
|
|
9
|
+
"id" TEXT NOT NULL,
|
|
10
|
+
"startsAt" TIMESTAMP(3) NOT NULL,
|
|
11
|
+
"durationMinutes" INTEGER NOT NULL DEFAULT 30,
|
|
12
|
+
"status" "MeetingSlotStatus" NOT NULL DEFAULT 'AVAILABLE',
|
|
13
|
+
"holdExpiresAt" TIMESTAMP(3),
|
|
14
|
+
"note" TEXT,
|
|
15
|
+
"createdByAdminEmail" TEXT,
|
|
16
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
17
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
18
|
+
|
|
19
|
+
CONSTRAINT "MeetingSlot_pkey" PRIMARY KEY ("id")
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- CreateTable
|
|
23
|
+
CREATE TABLE "MeetingBooking" (
|
|
24
|
+
"id" TEXT NOT NULL,
|
|
25
|
+
"slotId" TEXT NOT NULL,
|
|
26
|
+
"status" "MeetingBookingStatus" NOT NULL DEFAULT 'OTP_PENDING',
|
|
27
|
+
"name" TEXT,
|
|
28
|
+
"email" TEXT NOT NULL,
|
|
29
|
+
"phone" TEXT NOT NULL,
|
|
30
|
+
"visitorNote" TEXT,
|
|
31
|
+
"publicToken" TEXT NOT NULL,
|
|
32
|
+
"bulkgateId" TEXT,
|
|
33
|
+
"otpExpiresAt" TIMESTAMP(3),
|
|
34
|
+
"holdExpiresAt" TIMESTAMP(3),
|
|
35
|
+
"phoneVerifiedAt" TIMESTAMP(3),
|
|
36
|
+
"slotStartAt" TIMESTAMP(3) NOT NULL,
|
|
37
|
+
"slotEndAt" TIMESTAMP(3) NOT NULL,
|
|
38
|
+
"adminNote" TEXT,
|
|
39
|
+
"adminActionBy" TEXT,
|
|
40
|
+
"acceptedAt" TIMESTAMP(3),
|
|
41
|
+
"declinedAt" TIMESTAMP(3),
|
|
42
|
+
"canceledAt" TIMESTAMP(3),
|
|
43
|
+
"completedAt" TIMESTAMP(3),
|
|
44
|
+
"noShowAt" TIMESTAMP(3),
|
|
45
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
46
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
47
|
+
|
|
48
|
+
CONSTRAINT "MeetingBooking_pkey" PRIMARY KEY ("id")
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
-- CreateTable
|
|
52
|
+
CREATE TABLE "MeetingBookingSettings" (
|
|
53
|
+
"id" TEXT NOT NULL DEFAULT 'default',
|
|
54
|
+
"bookingEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
55
|
+
"timezone" TEXT NOT NULL DEFAULT 'Europe/Bratislava',
|
|
56
|
+
"bookingHorizonDays" INTEGER NOT NULL DEFAULT 30,
|
|
57
|
+
"minLeadHours" INTEGER NOT NULL DEFAULT 12,
|
|
58
|
+
"adminNotificationEmail" TEXT NOT NULL DEFAULT 'info@smartlex.sk',
|
|
59
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
60
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
61
|
+
|
|
62
|
+
CONSTRAINT "MeetingBookingSettings_pkey" PRIMARY KEY ("id")
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
-- CreateIndex
|
|
66
|
+
CREATE INDEX "MeetingSlot_status_startsAt_idx" ON "MeetingSlot"("status", "startsAt");
|
|
67
|
+
|
|
68
|
+
-- CreateIndex
|
|
69
|
+
CREATE INDEX "MeetingSlot_startsAt_idx" ON "MeetingSlot"("startsAt");
|
|
70
|
+
|
|
71
|
+
-- CreateIndex
|
|
72
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "MeetingSlot_startsAt_duration_active_key"
|
|
73
|
+
ON "MeetingSlot"("startsAt", "durationMinutes")
|
|
74
|
+
WHERE "status" <> 'ARCHIVED';
|
|
75
|
+
|
|
76
|
+
-- CreateIndex
|
|
77
|
+
CREATE UNIQUE INDEX "MeetingBooking_publicToken_key" ON "MeetingBooking"("publicToken");
|
|
78
|
+
|
|
79
|
+
-- CreateIndex
|
|
80
|
+
CREATE UNIQUE INDEX "MeetingBooking_bulkgateId_key" ON "MeetingBooking"("bulkgateId");
|
|
81
|
+
|
|
82
|
+
-- CreateIndex
|
|
83
|
+
CREATE INDEX "MeetingBooking_slotId_idx" ON "MeetingBooking"("slotId");
|
|
84
|
+
|
|
85
|
+
-- CreateIndex
|
|
86
|
+
CREATE INDEX "MeetingBooking_status_createdAt_idx" ON "MeetingBooking"("status", "createdAt");
|
|
87
|
+
|
|
88
|
+
-- CreateIndex
|
|
89
|
+
CREATE INDEX "MeetingBooking_email_idx" ON "MeetingBooking"("email");
|
|
90
|
+
|
|
91
|
+
-- CreateIndex
|
|
92
|
+
CREATE INDEX "MeetingBooking_phone_idx" ON "MeetingBooking"("phone");
|
|
93
|
+
|
|
94
|
+
-- CreateIndex
|
|
95
|
+
CREATE INDEX "MeetingBooking_slotStartAt_idx" ON "MeetingBooking"("slotStartAt");
|
|
96
|
+
|
|
97
|
+
-- AddForeignKey
|
|
98
|
+
ALTER TABLE "MeetingBooking" ADD CONSTRAINT "MeetingBooking_slotId_fkey" FOREIGN KEY ("slotId") REFERENCES "MeetingSlot"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
99
|
+
|
|
100
|
+
INSERT INTO "MeetingBookingSettings" ("id", "updatedAt")
|
|
101
|
+
VALUES ('default', CURRENT_TIMESTAMP)
|
|
102
|
+
ON CONFLICT ("id") DO NOTHING;
|