@danielcok17/prisma-db 1.19.2 → 1.20.0
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 +1 -2
- package/prisma/app.prisma +342 -433
- package/prisma/migrations/20260509171242_add_admin_grant_invoice_number/migration.sql +1 -0
- package/prisma/migrations/20260511135259_add_meeting_bookings/migration.sql +102 -0
- package/prisma/migrations/20260502185044_add_userfile_system/migration.sql +0 -194
- package/prisma/migrations/20260502204440_add_userfile_source_tracking/migration.sql +0 -50
- package/prisma/migrations/20260503104028_add_canvas_source_and_ai_generated/migration.sql +0 -5
package/prisma/app.prisma
CHANGED
|
@@ -30,118 +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
|
|
140
|
-
// Files & folders system
|
|
141
|
-
userFiles UserFile[] @relation("UserFiles")
|
|
142
|
-
reviewTables FileReviewTable[] @relation("UserReviewTables")
|
|
143
|
-
filesTotalBytes BigInt @default(0)
|
|
144
|
-
filesCount Int @default(0)
|
|
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")
|
|
145
140
|
|
|
146
141
|
// Multi-brand: compound unique allows same email across brands
|
|
147
142
|
@@unique([email, brand])
|
|
@@ -202,10 +197,10 @@ model Organization {
|
|
|
202
197
|
|
|
203
198
|
// Subscription (B2B)
|
|
204
199
|
subscriptionTier SubscriptionTier @default(FREE) // Tier organizácie (cache)
|
|
205
|
-
messageCount Int @default(0)
|
|
206
|
-
messageLimit Int @default(4)
|
|
207
|
-
messageCountResetAt DateTime?
|
|
208
|
-
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
|
|
209
204
|
|
|
210
205
|
// Settings
|
|
211
206
|
isActive Boolean @default(true)
|
|
@@ -292,13 +287,12 @@ model Conversation {
|
|
|
292
287
|
updatedAt DateTime @updatedAt
|
|
293
288
|
summary String?
|
|
294
289
|
messagesSinceLastSummary Int? @default(0)
|
|
295
|
-
integrityHash String?
|
|
290
|
+
integrityHash String? // HMAC-SHA256 hash chain - posledný chainHash pre verifikáciu integrity
|
|
296
291
|
// Relácie
|
|
297
292
|
answers Answer[]
|
|
298
293
|
user User @relation(fields: [userId], references: [id])
|
|
299
294
|
workflowLogs WorkflowLog[]
|
|
300
295
|
canvasDocuments CanvasDocument[]
|
|
301
|
-
fileUsages UserFileConversation[]
|
|
302
296
|
|
|
303
297
|
@@index([userId])
|
|
304
298
|
@@index([createdAt])
|
|
@@ -318,8 +312,8 @@ model Answer {
|
|
|
318
312
|
processingTime Int?
|
|
319
313
|
model String?
|
|
320
314
|
userId String?
|
|
321
|
-
contentHash String?
|
|
322
|
-
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
|
|
323
317
|
createdAt DateTime @default(now())
|
|
324
318
|
updatedAt DateTime @updatedAt
|
|
325
319
|
// Relácie
|
|
@@ -331,6 +325,7 @@ model Answer {
|
|
|
331
325
|
WorkflowLog WorkflowLog[]
|
|
332
326
|
files MessageFile[]
|
|
333
327
|
canvasDocumentId String? // No FK constraint - flexible document management
|
|
328
|
+
|
|
334
329
|
@@index([conversationId])
|
|
335
330
|
@@index([messageId])
|
|
336
331
|
@@index([role])
|
|
@@ -339,13 +334,13 @@ model Answer {
|
|
|
339
334
|
}
|
|
340
335
|
|
|
341
336
|
model MessageFile {
|
|
342
|
-
id
|
|
343
|
-
answerId
|
|
344
|
-
fileName
|
|
345
|
-
fileType
|
|
346
|
-
base64Data
|
|
347
|
-
uploadedAt
|
|
348
|
-
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)
|
|
349
344
|
|
|
350
345
|
@@index([answerId])
|
|
351
346
|
@@index([fileType])
|
|
@@ -852,11 +847,11 @@ enum CustomerType {
|
|
|
852
847
|
|
|
853
848
|
// Stripe: Tier predplatného
|
|
854
849
|
enum SubscriptionTier {
|
|
855
|
-
FREE
|
|
856
|
-
LAWYER
|
|
857
|
-
LAWYER_PRO
|
|
858
|
-
LAW_FIRM
|
|
859
|
-
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)
|
|
860
855
|
}
|
|
861
856
|
|
|
862
857
|
// Stripe: Billing interval
|
|
@@ -895,8 +890,7 @@ enum FolderItemType {
|
|
|
895
890
|
CONVERSATION
|
|
896
891
|
CANVAS_DOCUMENT
|
|
897
892
|
REFERENCE
|
|
898
|
-
ATTACHMENT
|
|
899
|
-
USER_FILE
|
|
893
|
+
ATTACHMENT
|
|
900
894
|
}
|
|
901
895
|
|
|
902
896
|
// Folder activity types (for timeline)
|
|
@@ -908,42 +902,10 @@ enum FolderActivityType {
|
|
|
908
902
|
ITEM_ADDED
|
|
909
903
|
ITEM_REMOVED
|
|
910
904
|
ITEM_UPDATED
|
|
911
|
-
ITEM_MOVED
|
|
912
905
|
SHARE_ADDED
|
|
913
906
|
SHARE_REMOVED
|
|
914
907
|
USER_MESSAGE
|
|
915
908
|
USER_NOTE
|
|
916
|
-
FILE_INDEXED
|
|
917
|
-
FILE_INDEX_ERROR
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
enum UserFileStatus {
|
|
921
|
-
STORED
|
|
922
|
-
QUEUED
|
|
923
|
-
INDEXING
|
|
924
|
-
INDEXED
|
|
925
|
-
ERROR
|
|
926
|
-
DELETED
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
enum UserFileUploadSource {
|
|
930
|
-
FOLDER // nahraté cez UI priečinka / prípadu
|
|
931
|
-
CHAT // nahraté z chatovej konverzácie
|
|
932
|
-
STORAGE // nahraté priamo do "Môj archív"
|
|
933
|
-
CANVAS // AI-vygenerovaný dokument uložený z canvas editora
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
enum IndexingJobStatus {
|
|
937
|
-
QUEUED
|
|
938
|
-
RUNNING
|
|
939
|
-
COMPLETED
|
|
940
|
-
FAILED
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
enum FolderType {
|
|
944
|
-
PERSONAL
|
|
945
|
-
MATTER
|
|
946
|
-
KNOWLEDGE_BASE
|
|
947
909
|
}
|
|
948
910
|
|
|
949
911
|
// Folder permission levels
|
|
@@ -1071,19 +1033,81 @@ model PasswordResetToken {
|
|
|
1071
1033
|
|
|
1072
1034
|
// Phone OTP verification (BulkGate)
|
|
1073
1035
|
model PhoneOtp {
|
|
1074
|
-
id
|
|
1075
|
-
userId
|
|
1076
|
-
phone
|
|
1077
|
-
bulkgateId
|
|
1078
|
-
expiresAt
|
|
1079
|
-
createdAt
|
|
1080
|
-
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)
|
|
1081
1043
|
|
|
1082
1044
|
@@index([userId])
|
|
1083
1045
|
@@index([bulkgateId])
|
|
1084
1046
|
@@index([expiresAt])
|
|
1085
1047
|
}
|
|
1086
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
|
+
|
|
1087
1111
|
// ============================================
|
|
1088
1112
|
// INGESTION PIPELINE MODELS
|
|
1089
1113
|
// ============================================
|
|
@@ -1103,7 +1127,7 @@ model IngestedDocument {
|
|
|
1103
1127
|
references String[] // Legal references from classification
|
|
1104
1128
|
chunkCount Int?
|
|
1105
1129
|
embeddingCost Float? // EUR
|
|
1106
|
-
qdrantDocId String?
|
|
1130
|
+
qdrantDocId String? @unique // doc_id used in Qdrant vector payloads
|
|
1107
1131
|
folderId String? // Optional folder association
|
|
1108
1132
|
storagePath String? // Local filesystem path (dev/staging)
|
|
1109
1133
|
storageUrl String? // Cloud storage URL (prod — S3/DigitalOcean Spaces)
|
|
@@ -1127,138 +1151,6 @@ enum IngestionStatus {
|
|
|
1127
1151
|
ERROR
|
|
1128
1152
|
}
|
|
1129
1153
|
|
|
1130
|
-
model UserFile {
|
|
1131
|
-
id String @id @default(cuid())
|
|
1132
|
-
userId String
|
|
1133
|
-
|
|
1134
|
-
storageKey String @unique
|
|
1135
|
-
storageUrl String?
|
|
1136
|
-
checksumSha256 String
|
|
1137
|
-
|
|
1138
|
-
fileName String
|
|
1139
|
-
fileType String
|
|
1140
|
-
fileSize Int
|
|
1141
|
-
pageCount Int?
|
|
1142
|
-
language String? @default("sk")
|
|
1143
|
-
|
|
1144
|
-
status UserFileStatus @default(STORED)
|
|
1145
|
-
|
|
1146
|
-
docType String?
|
|
1147
|
-
legalArea String?
|
|
1148
|
-
summary String?
|
|
1149
|
-
extractedData Json?
|
|
1150
|
-
references String[] @default([])
|
|
1151
|
-
chunkCount Int?
|
|
1152
|
-
qdrantDocId String? @unique
|
|
1153
|
-
indexingCost Float?
|
|
1154
|
-
indexedAt DateTime?
|
|
1155
|
-
indexError String?
|
|
1156
|
-
|
|
1157
|
-
tags String[] @default([])
|
|
1158
|
-
|
|
1159
|
-
parentFileId String?
|
|
1160
|
-
versionNumber Int @default(1)
|
|
1161
|
-
|
|
1162
|
-
uploadSource UserFileUploadSource @default(STORAGE)
|
|
1163
|
-
uploadContextId String? // polymorphic: folderId | conversationId | documentId | null
|
|
1164
|
-
isAiGenerated Boolean @default(false) // true = AI vygeneroval obsah (canvas export)
|
|
1165
|
-
|
|
1166
|
-
createdAt DateTime @default(now())
|
|
1167
|
-
updatedAt DateTime @updatedAt
|
|
1168
|
-
deletedAt DateTime?
|
|
1169
|
-
|
|
1170
|
-
user User @relation("UserFiles", fields: [userId], references: [id], onDelete: Cascade)
|
|
1171
|
-
indexingJobs FileIndexingJob[]
|
|
1172
|
-
deadlines FileDeadline[]
|
|
1173
|
-
parentFile UserFile? @relation("FileVersions", fields: [parentFileId], references: [id], onDelete: SetNull)
|
|
1174
|
-
childVersions UserFile[] @relation("FileVersions")
|
|
1175
|
-
conversationUsages UserFileConversation[]
|
|
1176
|
-
|
|
1177
|
-
@@index([userId])
|
|
1178
|
-
@@index([status])
|
|
1179
|
-
@@index([userId, status])
|
|
1180
|
-
@@index([userId, deletedAt])
|
|
1181
|
-
@@index([qdrantDocId])
|
|
1182
|
-
@@index([uploadSource])
|
|
1183
|
-
@@index([uploadContextId])
|
|
1184
|
-
@@index([checksumSha256])
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
model UserFileConversation {
|
|
1188
|
-
id String @id @default(cuid())
|
|
1189
|
-
fileId String
|
|
1190
|
-
conversationId String
|
|
1191
|
-
createdAt DateTime @default(now())
|
|
1192
|
-
|
|
1193
|
-
file UserFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
|
|
1194
|
-
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
|
1195
|
-
|
|
1196
|
-
@@unique([fileId, conversationId])
|
|
1197
|
-
@@index([fileId])
|
|
1198
|
-
@@index([conversationId])
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
model FileIndexingJob {
|
|
1202
|
-
id String @id @default(cuid())
|
|
1203
|
-
fileId String
|
|
1204
|
-
userId String
|
|
1205
|
-
status IndexingJobStatus @default(QUEUED)
|
|
1206
|
-
attempts Int @default(0)
|
|
1207
|
-
maxAttempts Int @default(3)
|
|
1208
|
-
errorMsg String?
|
|
1209
|
-
startedAt DateTime?
|
|
1210
|
-
finishedAt DateTime?
|
|
1211
|
-
createdAt DateTime @default(now())
|
|
1212
|
-
|
|
1213
|
-
file UserFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
|
|
1214
|
-
|
|
1215
|
-
@@index([fileId])
|
|
1216
|
-
@@index([userId])
|
|
1217
|
-
@@index([status])
|
|
1218
|
-
@@index([createdAt])
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
model FileDeadline {
|
|
1222
|
-
id String @id @default(cuid())
|
|
1223
|
-
fileId String
|
|
1224
|
-
userId String
|
|
1225
|
-
label String
|
|
1226
|
-
deadlineAt DateTime
|
|
1227
|
-
notifyAt DateTime?
|
|
1228
|
-
isNotified Boolean @default(false)
|
|
1229
|
-
isDismissed Boolean @default(false)
|
|
1230
|
-
sourceSection String?
|
|
1231
|
-
sourcePage Int?
|
|
1232
|
-
createdAt DateTime @default(now())
|
|
1233
|
-
|
|
1234
|
-
file UserFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
|
|
1235
|
-
|
|
1236
|
-
@@index([fileId])
|
|
1237
|
-
@@index([userId])
|
|
1238
|
-
@@index([deadlineAt])
|
|
1239
|
-
@@index([notifyAt, isNotified])
|
|
1240
|
-
@@index([userId, isDismissed])
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
model FileReviewTable {
|
|
1244
|
-
id String @id @default(cuid())
|
|
1245
|
-
userId String
|
|
1246
|
-
folderId String?
|
|
1247
|
-
name String
|
|
1248
|
-
columns Json
|
|
1249
|
-
fileIds String[] @default([])
|
|
1250
|
-
results Json?
|
|
1251
|
-
status String @default("draft")
|
|
1252
|
-
createdAt DateTime @default(now())
|
|
1253
|
-
updatedAt DateTime @updatedAt
|
|
1254
|
-
|
|
1255
|
-
user User @relation("UserReviewTables", fields: [userId], references: [id], onDelete: Cascade)
|
|
1256
|
-
|
|
1257
|
-
@@index([userId])
|
|
1258
|
-
@@index([folderId])
|
|
1259
|
-
@@index([status])
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
1154
|
enum LifecycleStage {
|
|
1263
1155
|
REGISTERED
|
|
1264
1156
|
ACTIVATED
|
|
@@ -1324,14 +1216,33 @@ enum ReferralStatus {
|
|
|
1324
1216
|
}
|
|
1325
1217
|
|
|
1326
1218
|
enum InvoiceGrantStatus {
|
|
1327
|
-
PENDING
|
|
1328
|
-
PAID
|
|
1329
|
-
VOID
|
|
1219
|
+
PENDING // Faktúra odoslaná, čaká na platbu
|
|
1220
|
+
PAID // Zaplatené, grant aktívny
|
|
1221
|
+
VOID // Stornovaná (admin alebo Stripe)
|
|
1330
1222
|
}
|
|
1331
1223
|
|
|
1332
1224
|
enum CollectionMethod {
|
|
1333
1225
|
CHARGE_AUTOMATICALLY // Automatické strhnutie kartou
|
|
1334
|
-
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
|
|
1335
1246
|
}
|
|
1336
1247
|
|
|
1337
1248
|
// ============================================
|
|
@@ -1407,9 +1318,6 @@ model Folder {
|
|
|
1407
1318
|
path String @default("/") // Materialized path: "/parentId/grandparentId/..."
|
|
1408
1319
|
depth Int @default(0)
|
|
1409
1320
|
|
|
1410
|
-
// Folder type
|
|
1411
|
-
folderType FolderType @default(PERSONAL)
|
|
1412
|
-
|
|
1413
1321
|
// Metadata
|
|
1414
1322
|
sortOrder Int @default(0)
|
|
1415
1323
|
isArchived Boolean @default(false)
|
|
@@ -1547,6 +1455,7 @@ model AdminGrant {
|
|
|
1547
1455
|
isActive Boolean @default(true)
|
|
1548
1456
|
revokedAt DateTime?
|
|
1549
1457
|
revokedBy String?
|
|
1458
|
+
invoiceNumber String?
|
|
1550
1459
|
createdAt DateTime @default(now())
|
|
1551
1460
|
updatedAt DateTime @updatedAt
|
|
1552
1461
|
|
|
@@ -1562,20 +1471,20 @@ model AdminGrant {
|
|
|
1562
1471
|
// One-off admin invoice — standalone faktúra pre špeciálne prípady (demo, trial, custom deal)
|
|
1563
1472
|
// Pre recurring fakturáciu použiť StripeSubscription s collectionMethod=SEND_INVOICE
|
|
1564
1473
|
model InvoiceGrant {
|
|
1565
|
-
id
|
|
1566
|
-
userId
|
|
1567
|
-
organizationId
|
|
1568
|
-
stripeInvoiceId
|
|
1569
|
-
tier
|
|
1570
|
-
durationDays
|
|
1571
|
-
amount
|
|
1572
|
-
status
|
|
1573
|
-
grantId
|
|
1574
|
-
createdBy
|
|
1575
|
-
notes
|
|
1576
|
-
paidAt
|
|
1577
|
-
createdAt
|
|
1578
|
-
updatedAt
|
|
1474
|
+
id String @id @default(cuid())
|
|
1475
|
+
userId String?
|
|
1476
|
+
organizationId String?
|
|
1477
|
+
stripeInvoiceId String @unique
|
|
1478
|
+
tier SubscriptionTier
|
|
1479
|
+
durationDays Int // Na koľko dní sa aktivuje grant po platbe
|
|
1480
|
+
amount Int // Suma v centoch (EUR)
|
|
1481
|
+
status InvoiceGrantStatus @default(PENDING)
|
|
1482
|
+
grantId String? // ID AdminGrantu vytvoreného po platbe
|
|
1483
|
+
createdBy String // Admin email
|
|
1484
|
+
notes String?
|
|
1485
|
+
paidAt DateTime?
|
|
1486
|
+
createdAt DateTime @default(now())
|
|
1487
|
+
updatedAt DateTime @updatedAt
|
|
1579
1488
|
|
|
1580
1489
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1581
1490
|
organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
@@ -1613,39 +1522,39 @@ model AppInvite {
|
|
|
1613
1522
|
// ============================================
|
|
1614
1523
|
|
|
1615
1524
|
model EmailSend {
|
|
1616
|
-
id
|
|
1617
|
-
userId
|
|
1618
|
-
templateSlug
|
|
1619
|
-
campaignId
|
|
1620
|
-
|
|
1621
|
-
status
|
|
1622
|
-
sentAt
|
|
1623
|
-
deliveredAt
|
|
1624
|
-
toEmail
|
|
1625
|
-
fromEmail
|
|
1626
|
-
|
|
1627
|
-
openedAt
|
|
1628
|
-
openCount
|
|
1629
|
-
clickedAt
|
|
1630
|
-
clickCount
|
|
1631
|
-
|
|
1632
|
-
bouncedAt
|
|
1633
|
-
bounceType
|
|
1634
|
-
complainedAt
|
|
1635
|
-
unsubscribedAt
|
|
1636
|
-
|
|
1637
|
-
errorMessage
|
|
1638
|
-
errorCode
|
|
1525
|
+
id String @id @default(cuid())
|
|
1526
|
+
userId String?
|
|
1527
|
+
templateSlug String
|
|
1528
|
+
campaignId String?
|
|
1529
|
+
|
|
1530
|
+
status EmailStatus @default(QUEUED)
|
|
1531
|
+
sentAt DateTime?
|
|
1532
|
+
deliveredAt DateTime?
|
|
1533
|
+
toEmail String
|
|
1534
|
+
fromEmail String @default("info@mail.smartlex.sk")
|
|
1535
|
+
|
|
1536
|
+
openedAt DateTime?
|
|
1537
|
+
openCount Int @default(0)
|
|
1538
|
+
clickedAt DateTime?
|
|
1539
|
+
clickCount Int @default(0)
|
|
1540
|
+
|
|
1541
|
+
bouncedAt DateTime?
|
|
1542
|
+
bounceType BounceType?
|
|
1543
|
+
complainedAt DateTime?
|
|
1544
|
+
unsubscribedAt DateTime?
|
|
1545
|
+
|
|
1546
|
+
errorMessage String?
|
|
1547
|
+
errorCode String?
|
|
1548
|
+
|
|
1549
|
+
subjectLine String?
|
|
1550
|
+
espMessageId String? @unique
|
|
1551
|
+
idempotencyKey String? @unique
|
|
1552
|
+
isTransactional Boolean @default(false)
|
|
1553
|
+
metadata Json?
|
|
1639
1554
|
|
|
1640
|
-
|
|
1641
|
-
espMessageId String? @unique
|
|
1642
|
-
idempotencyKey String? @unique
|
|
1643
|
-
isTransactional Boolean @default(false)
|
|
1644
|
-
metadata Json?
|
|
1645
|
-
|
|
1646
|
-
createdAt DateTime @default(now())
|
|
1555
|
+
createdAt DateTime @default(now())
|
|
1647
1556
|
|
|
1648
|
-
user
|
|
1557
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
1649
1558
|
|
|
1650
1559
|
@@index([userId])
|
|
1651
1560
|
@@index([templateSlug])
|
|
@@ -1659,43 +1568,43 @@ model EmailSend {
|
|
|
1659
1568
|
}
|
|
1660
1569
|
|
|
1661
1570
|
model EmailSequence {
|
|
1662
|
-
id
|
|
1663
|
-
slug
|
|
1664
|
-
name
|
|
1665
|
-
description
|
|
1666
|
-
triggerEvent
|
|
1667
|
-
isActive
|
|
1571
|
+
id String @id @default(cuid())
|
|
1572
|
+
slug String @unique
|
|
1573
|
+
name String
|
|
1574
|
+
description String?
|
|
1575
|
+
triggerEvent String
|
|
1576
|
+
isActive Boolean @default(true)
|
|
1668
1577
|
|
|
1669
|
-
steps
|
|
1670
|
-
enrollments
|
|
1578
|
+
steps EmailSequenceStep[]
|
|
1579
|
+
enrollments EmailSequenceEnrollment[]
|
|
1671
1580
|
|
|
1672
|
-
createdAt
|
|
1673
|
-
updatedAt
|
|
1581
|
+
createdAt DateTime @default(now())
|
|
1582
|
+
updatedAt DateTime @updatedAt
|
|
1674
1583
|
}
|
|
1675
1584
|
|
|
1676
1585
|
model EmailSequenceStep {
|
|
1677
|
-
id String
|
|
1586
|
+
id String @id @default(cuid())
|
|
1678
1587
|
sequenceId String
|
|
1679
1588
|
templateSlug String
|
|
1680
1589
|
stepOrder Int
|
|
1681
|
-
delayMinutes Int
|
|
1590
|
+
delayMinutes Int @default(0)
|
|
1682
1591
|
sendCondition Json?
|
|
1683
1592
|
skipCondition Json?
|
|
1684
|
-
isActive Boolean
|
|
1593
|
+
isActive Boolean @default(true)
|
|
1685
1594
|
|
|
1686
|
-
sequence
|
|
1595
|
+
sequence EmailSequence @relation(fields: [sequenceId], references: [id], onDelete: Cascade)
|
|
1687
1596
|
|
|
1688
|
-
createdAt
|
|
1597
|
+
createdAt DateTime @default(now())
|
|
1689
1598
|
|
|
1690
1599
|
@@unique([sequenceId, stepOrder])
|
|
1691
1600
|
}
|
|
1692
1601
|
|
|
1693
1602
|
model EmailSequenceEnrollment {
|
|
1694
|
-
id
|
|
1695
|
-
userId
|
|
1696
|
-
sequenceId
|
|
1697
|
-
currentStep
|
|
1698
|
-
status
|
|
1603
|
+
id String @id @default(cuid())
|
|
1604
|
+
userId String
|
|
1605
|
+
sequenceId String
|
|
1606
|
+
currentStep Int @default(0)
|
|
1607
|
+
status EnrollmentStatus @default(ACTIVE)
|
|
1699
1608
|
|
|
1700
1609
|
enrolledAt DateTime @default(now())
|
|
1701
1610
|
completedAt DateTime?
|
|
@@ -1704,51 +1613,51 @@ model EmailSequenceEnrollment {
|
|
|
1704
1613
|
nextSendAt DateTime?
|
|
1705
1614
|
processingLockedAt DateTime?
|
|
1706
1615
|
|
|
1707
|
-
user
|
|
1708
|
-
sequence
|
|
1616
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1617
|
+
sequence EmailSequence @relation(fields: [sequenceId], references: [id])
|
|
1709
1618
|
|
|
1710
1619
|
@@index([status, nextSendAt])
|
|
1711
1620
|
@@index([userId, sequenceId, status])
|
|
1712
1621
|
}
|
|
1713
1622
|
|
|
1714
1623
|
model EmailConsent {
|
|
1715
|
-
id
|
|
1716
|
-
userId
|
|
1624
|
+
id String @id @default(cuid())
|
|
1625
|
+
userId String @unique
|
|
1717
1626
|
|
|
1718
|
-
marketingConsent
|
|
1719
|
-
productUpdatesConsent
|
|
1720
|
-
legalNewsConsent
|
|
1627
|
+
marketingConsent Boolean @default(false)
|
|
1628
|
+
productUpdatesConsent Boolean @default(false)
|
|
1629
|
+
legalNewsConsent Boolean @default(false)
|
|
1721
1630
|
|
|
1722
|
-
doubleOptinSentAt
|
|
1723
|
-
doubleOptinConfirmedAt
|
|
1724
|
-
doubleOptinToken
|
|
1631
|
+
doubleOptinSentAt DateTime?
|
|
1632
|
+
doubleOptinConfirmedAt DateTime?
|
|
1633
|
+
doubleOptinToken String? @unique
|
|
1725
1634
|
|
|
1726
|
-
user
|
|
1727
|
-
history
|
|
1635
|
+
user User @relation(fields: [userId], references: [id], onDelete: Restrict)
|
|
1636
|
+
history EmailConsentHistory[]
|
|
1728
1637
|
|
|
1729
|
-
createdAt
|
|
1730
|
-
updatedAt
|
|
1638
|
+
createdAt DateTime @default(now())
|
|
1639
|
+
updatedAt DateTime @updatedAt
|
|
1731
1640
|
}
|
|
1732
1641
|
|
|
1733
1642
|
model EmailConsentHistory {
|
|
1734
|
-
id
|
|
1735
|
-
consentId
|
|
1736
|
-
userId
|
|
1643
|
+
id String @id @default(cuid())
|
|
1644
|
+
consentId String
|
|
1645
|
+
userId String
|
|
1737
1646
|
|
|
1738
|
-
action
|
|
1739
|
-
channel
|
|
1740
|
-
oldValue
|
|
1741
|
-
newValue
|
|
1647
|
+
action ConsentAction
|
|
1648
|
+
channel String
|
|
1649
|
+
oldValue Boolean?
|
|
1650
|
+
newValue Boolean
|
|
1742
1651
|
|
|
1743
|
-
consentText
|
|
1744
|
-
consentVersion
|
|
1745
|
-
consentMethod
|
|
1746
|
-
ipAddress
|
|
1747
|
-
userAgent
|
|
1652
|
+
consentText String
|
|
1653
|
+
consentVersion String
|
|
1654
|
+
consentMethod String
|
|
1655
|
+
ipAddress String?
|
|
1656
|
+
userAgent String?
|
|
1748
1657
|
|
|
1749
|
-
consent
|
|
1658
|
+
consent EmailConsent @relation(fields: [consentId], references: [id], onDelete: Restrict)
|
|
1750
1659
|
|
|
1751
|
-
createdAt
|
|
1660
|
+
createdAt DateTime @default(now())
|
|
1752
1661
|
|
|
1753
1662
|
@@index([userId, createdAt])
|
|
1754
1663
|
@@index([consentId])
|
|
@@ -1756,25 +1665,25 @@ model EmailConsentHistory {
|
|
|
1756
1665
|
}
|
|
1757
1666
|
|
|
1758
1667
|
model UserScore {
|
|
1759
|
-
id
|
|
1760
|
-
userId
|
|
1761
|
-
score
|
|
1762
|
-
leadSegment
|
|
1763
|
-
churnRisk
|
|
1668
|
+
id String @id @default(cuid())
|
|
1669
|
+
userId String @unique
|
|
1670
|
+
score Int @default(0)
|
|
1671
|
+
leadSegment LeadSegment @default(COLD)
|
|
1672
|
+
churnRisk ChurnRisk @default(NONE)
|
|
1764
1673
|
|
|
1765
|
-
signupScore Int
|
|
1766
|
-
engagementScore Int
|
|
1767
|
-
usageScore Int
|
|
1768
|
-
intentScore Int
|
|
1769
|
-
decayScore Int
|
|
1674
|
+
signupScore Int @default(0)
|
|
1675
|
+
engagementScore Int @default(0)
|
|
1676
|
+
usageScore Int @default(0)
|
|
1677
|
+
intentScore Int @default(0)
|
|
1678
|
+
decayScore Int @default(0)
|
|
1770
1679
|
|
|
1771
|
-
lastActivityAt
|
|
1772
|
-
scoreUpdatedAt
|
|
1680
|
+
lastActivityAt DateTime?
|
|
1681
|
+
scoreUpdatedAt DateTime @default(now())
|
|
1773
1682
|
|
|
1774
|
-
user
|
|
1775
|
-
events
|
|
1683
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1684
|
+
events UserScoreEvent[]
|
|
1776
1685
|
|
|
1777
|
-
createdAt
|
|
1686
|
+
createdAt DateTime @default(now())
|
|
1778
1687
|
|
|
1779
1688
|
@@index([score])
|
|
1780
1689
|
@@index([leadSegment])
|
|
@@ -1782,18 +1691,18 @@ model UserScore {
|
|
|
1782
1691
|
}
|
|
1783
1692
|
|
|
1784
1693
|
model UserScoreEvent {
|
|
1785
|
-
id
|
|
1786
|
-
userScoreId
|
|
1787
|
-
userId
|
|
1788
|
-
eventType
|
|
1789
|
-
pointsDelta
|
|
1790
|
-
scoreBefore
|
|
1791
|
-
scoreAfter
|
|
1792
|
-
metadata
|
|
1694
|
+
id String @id @default(cuid())
|
|
1695
|
+
userScoreId String
|
|
1696
|
+
userId String
|
|
1697
|
+
eventType String
|
|
1698
|
+
pointsDelta Int
|
|
1699
|
+
scoreBefore Int
|
|
1700
|
+
scoreAfter Int
|
|
1701
|
+
metadata Json?
|
|
1793
1702
|
|
|
1794
|
-
userScore
|
|
1703
|
+
userScore UserScore @relation(fields: [userScoreId], references: [id], onDelete: Cascade)
|
|
1795
1704
|
|
|
1796
|
-
createdAt
|
|
1705
|
+
createdAt DateTime @default(now())
|
|
1797
1706
|
|
|
1798
1707
|
@@index([userId, createdAt])
|
|
1799
1708
|
@@index([userScoreId])
|
|
@@ -1802,35 +1711,35 @@ model UserScoreEvent {
|
|
|
1802
1711
|
}
|
|
1803
1712
|
|
|
1804
1713
|
model EmailSuppression {
|
|
1805
|
-
id
|
|
1806
|
-
email
|
|
1807
|
-
reason
|
|
1808
|
-
source
|
|
1714
|
+
id String @id @default(cuid())
|
|
1715
|
+
email String
|
|
1716
|
+
reason SuppressionReason
|
|
1717
|
+
source String?
|
|
1809
1718
|
|
|
1810
|
-
suppressedAt
|
|
1719
|
+
suppressedAt DateTime @default(now())
|
|
1811
1720
|
|
|
1812
1721
|
@@unique([email, reason])
|
|
1813
1722
|
@@index([email])
|
|
1814
1723
|
}
|
|
1815
1724
|
|
|
1816
1725
|
model Referral {
|
|
1817
|
-
id
|
|
1818
|
-
referrerId
|
|
1819
|
-
referredUserId
|
|
1820
|
-
referredEmail
|
|
1821
|
-
status
|
|
1822
|
-
referralCode
|
|
1823
|
-
|
|
1824
|
-
rewardType
|
|
1825
|
-
rewardedAt
|
|
1826
|
-
clickCount
|
|
1827
|
-
registeredAt
|
|
1828
|
-
convertedAt
|
|
1829
|
-
|
|
1830
|
-
createdAt
|
|
1831
|
-
|
|
1832
|
-
referrer
|
|
1833
|
-
referredUser
|
|
1726
|
+
id String @id @default(cuid())
|
|
1727
|
+
referrerId String?
|
|
1728
|
+
referredUserId String?
|
|
1729
|
+
referredEmail String?
|
|
1730
|
+
status ReferralStatus @default(PENDING)
|
|
1731
|
+
referralCode String @unique
|
|
1732
|
+
|
|
1733
|
+
rewardType String?
|
|
1734
|
+
rewardedAt DateTime?
|
|
1735
|
+
clickCount Int @default(0)
|
|
1736
|
+
registeredAt DateTime?
|
|
1737
|
+
convertedAt DateTime?
|
|
1738
|
+
|
|
1739
|
+
createdAt DateTime @default(now())
|
|
1740
|
+
|
|
1741
|
+
referrer User? @relation("ReferralsSent", fields: [referrerId], references: [id], onDelete: SetNull)
|
|
1742
|
+
referredUser User? @relation("ReferralsReceived", fields: [referredUserId], references: [id], onDelete: SetNull)
|
|
1834
1743
|
|
|
1835
1744
|
@@index([referrerId])
|
|
1836
1745
|
@@index([referredUserId])
|