@ken2008/zapit-schema 0.1.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/README.md +16 -0
- package/generated/prisma/client.d.ts +1 -0
- package/generated/prisma/client.js +5 -0
- package/generated/prisma/default.d.ts +1 -0
- package/generated/prisma/default.js +5 -0
- package/generated/prisma/edge.d.ts +1 -0
- package/generated/prisma/edge.js +3072 -0
- package/generated/prisma/index-browser.js +3098 -0
- package/generated/prisma/index.d.ts +359962 -0
- package/generated/prisma/index.js +3072 -0
- package/generated/prisma/package.json +144 -0
- package/generated/prisma/query_compiler_fast_bg.js +2 -0
- package/generated/prisma/query_compiler_fast_bg.wasm +0 -0
- package/generated/prisma/query_compiler_fast_bg.wasm-base64.js +2 -0
- package/generated/prisma/runtime/client.d.ts +3330 -0
- package/generated/prisma/runtime/client.js +86 -0
- package/generated/prisma/runtime/index-browser.d.ts +87 -0
- package/generated/prisma/runtime/index-browser.js +6 -0
- package/generated/prisma/runtime/wasm-compiler-edge.js +76 -0
- package/generated/prisma/schema.prisma +3735 -0
- package/generated/prisma/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma/wasm-worker-loader.mjs +5 -0
- package/package.json +37 -0
- package/prisma/migrations/20250507132411_zapit/migration.sql +183 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +3735 -0
|
@@ -0,0 +1,3735 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
output = "../generated/prisma"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
datasource db {
|
|
7
|
+
provider = "postgresql"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
enum UserStatus {
|
|
11
|
+
ACTIVE
|
|
12
|
+
SUSPENDED
|
|
13
|
+
BANNED
|
|
14
|
+
PENDING_DELETION
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum WebsiteStatusCode {
|
|
18
|
+
OPERATIONAL
|
|
19
|
+
MAINTENANCE
|
|
20
|
+
DEGRADED
|
|
21
|
+
OUTAGE
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
enum LobbyStatus {
|
|
25
|
+
WAITING
|
|
26
|
+
STARTED
|
|
27
|
+
GAME
|
|
28
|
+
QUESTION
|
|
29
|
+
SCOREBOARD
|
|
30
|
+
RESULTS
|
|
31
|
+
HALTED
|
|
32
|
+
ENDED
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
enum ParticipantStatus {
|
|
36
|
+
ACTIVE
|
|
37
|
+
KICKED
|
|
38
|
+
LEFT
|
|
39
|
+
FINISHED
|
|
40
|
+
LOADING
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
enum GameStatus {
|
|
44
|
+
WAITING
|
|
45
|
+
ACTIVE
|
|
46
|
+
FINISHED
|
|
47
|
+
CANCELLED
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
enum PublicationStatus {
|
|
51
|
+
DRAFT
|
|
52
|
+
PUBLISHED
|
|
53
|
+
ARCHIVED
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
enum Visibility {
|
|
57
|
+
PRIVATE
|
|
58
|
+
UNLISTED
|
|
59
|
+
PUBLIC
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
enum CourseLevel {
|
|
63
|
+
GCSE
|
|
64
|
+
AS_LEVEL
|
|
65
|
+
A_LEVEL
|
|
66
|
+
IB
|
|
67
|
+
UNIVERSITY
|
|
68
|
+
OTHER
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
enum LessonType {
|
|
72
|
+
VIDEO
|
|
73
|
+
INTERACTIVE
|
|
74
|
+
MIXED
|
|
75
|
+
READING
|
|
76
|
+
QUIZ
|
|
77
|
+
EXAM_PRACTICE
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
enum LessonStepType {
|
|
81
|
+
READING
|
|
82
|
+
INTERACTIVE
|
|
83
|
+
VIDEO
|
|
84
|
+
QUIZ
|
|
85
|
+
EXAM_PRACTICE
|
|
86
|
+
EXAM_MODE
|
|
87
|
+
FLASHCARDS
|
|
88
|
+
ACTIVITY
|
|
89
|
+
DOCUMENT
|
|
90
|
+
NOTES
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
enum VideoDifficulty {
|
|
94
|
+
BEGINNER
|
|
95
|
+
INTERMEDIATE
|
|
96
|
+
ADVANCED
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
enum QuestionType {
|
|
100
|
+
MULTIPLE_CHOICE
|
|
101
|
+
TRUE_FALSE
|
|
102
|
+
SHORT_ANSWER
|
|
103
|
+
LIST_ORDER
|
|
104
|
+
SELECT
|
|
105
|
+
FILL_BLANK
|
|
106
|
+
MATCHING
|
|
107
|
+
IMAGE_MCQ
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
enum ExamStatus {
|
|
111
|
+
DRAFT
|
|
112
|
+
PUBLISHED
|
|
113
|
+
ARCHIVED
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
enum ExamSessionStatus {
|
|
117
|
+
ACTIVE
|
|
118
|
+
SUBMITTED
|
|
119
|
+
GRADED
|
|
120
|
+
FLAGGED
|
|
121
|
+
EXPIRED
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
enum TutoringSessionStatus {
|
|
125
|
+
REQUESTED
|
|
126
|
+
SCHEDULED
|
|
127
|
+
CONFIRMED
|
|
128
|
+
IN_PROGRESS
|
|
129
|
+
COMPLETED
|
|
130
|
+
CANCELLED
|
|
131
|
+
NO_SHOW
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
enum TutoringSessionType {
|
|
135
|
+
INDIVIDUAL
|
|
136
|
+
GROUP
|
|
137
|
+
LIVE_DROP_IN
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
enum SessionFormat {
|
|
141
|
+
VIRTUAL
|
|
142
|
+
PHYSICAL
|
|
143
|
+
HYBRID
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
enum TutorVerificationStatus {
|
|
147
|
+
PENDING
|
|
148
|
+
APPROVED
|
|
149
|
+
REJECTED
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
enum EnrollmentStatus {
|
|
153
|
+
ACTIVE
|
|
154
|
+
INVITED
|
|
155
|
+
PAUSED
|
|
156
|
+
COMPLETED
|
|
157
|
+
DROPPED
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
enum ClassroomRole {
|
|
161
|
+
STUDENT
|
|
162
|
+
TEACHER
|
|
163
|
+
ASSISTANT
|
|
164
|
+
PARENT
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
enum AssignmentStatus {
|
|
168
|
+
DRAFT
|
|
169
|
+
PUBLISHED
|
|
170
|
+
CLOSED
|
|
171
|
+
ARCHIVED
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
enum SubmissionStatus {
|
|
175
|
+
NOT_STARTED
|
|
176
|
+
SUBMITTED
|
|
177
|
+
LATE
|
|
178
|
+
GRADED
|
|
179
|
+
RETURNED
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
enum ConversationType {
|
|
183
|
+
DIRECT
|
|
184
|
+
GROUP
|
|
185
|
+
SUPPORT
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
enum ConversationParticipantRole {
|
|
189
|
+
OWNER
|
|
190
|
+
MEMBER
|
|
191
|
+
AGENT
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
enum MessageSenderRole {
|
|
195
|
+
USER
|
|
196
|
+
AGENT
|
|
197
|
+
SYSTEM
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
enum AnnouncementStatus {
|
|
201
|
+
DRAFT
|
|
202
|
+
SCHEDULED
|
|
203
|
+
SENT
|
|
204
|
+
ARCHIVED
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
enum NotificationType {
|
|
208
|
+
MESSAGE
|
|
209
|
+
BOOKING
|
|
210
|
+
ASSIGNMENT
|
|
211
|
+
REVIEW
|
|
212
|
+
PAYMENT
|
|
213
|
+
SYSTEM
|
|
214
|
+
SECURITY
|
|
215
|
+
SUPPORT
|
|
216
|
+
GENERAL
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
enum NotificationChannel {
|
|
220
|
+
IN_APP
|
|
221
|
+
EMAIL
|
|
222
|
+
PUSH
|
|
223
|
+
SMS
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
enum SupportStatus {
|
|
227
|
+
OPEN
|
|
228
|
+
PENDING
|
|
229
|
+
IN_PROGRESS
|
|
230
|
+
RESOLVED
|
|
231
|
+
CLOSED
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
enum SupportPriority {
|
|
235
|
+
LOW
|
|
236
|
+
MEDIUM
|
|
237
|
+
HIGH
|
|
238
|
+
URGENT
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
enum FeedbackType {
|
|
242
|
+
BUG
|
|
243
|
+
FEATURE
|
|
244
|
+
CONTENT
|
|
245
|
+
CONFUSING
|
|
246
|
+
GENERAL
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
enum FeedbackStatus {
|
|
250
|
+
NEW
|
|
251
|
+
PENDING
|
|
252
|
+
IN_REVIEW
|
|
253
|
+
RESOLVED
|
|
254
|
+
ARCHIVED
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
enum CommunityVisibility {
|
|
258
|
+
PUBLIC
|
|
259
|
+
PRIVATE
|
|
260
|
+
RESTRICTED
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
enum CommunityResourceType {
|
|
264
|
+
LINK
|
|
265
|
+
FILE
|
|
266
|
+
NOTE
|
|
267
|
+
TEMPLATE
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
enum UserEventType {
|
|
271
|
+
TRIVIT
|
|
272
|
+
ZAPIT_QUIZ
|
|
273
|
+
LIVE_SESSION
|
|
274
|
+
STUDY_RACE
|
|
275
|
+
FLASHCARD_BATTLE
|
|
276
|
+
COMMUNITY_EVENT
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
enum UserEventStatus {
|
|
280
|
+
COMPLETED
|
|
281
|
+
ABANDONED
|
|
282
|
+
IN_PROGRESS
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
enum PlacementTier {
|
|
286
|
+
FIRST
|
|
287
|
+
SECOND
|
|
288
|
+
THIRD
|
|
289
|
+
TOP_TEN
|
|
290
|
+
PARTICIPATED
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
enum FeatureFlagStatus {
|
|
294
|
+
ENABLED
|
|
295
|
+
PARTIAL
|
|
296
|
+
DISABLED
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
enum DeploymentEnvironment {
|
|
300
|
+
DEVELOPMENT
|
|
301
|
+
STAGING
|
|
302
|
+
PRODUCTION
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
enum ExperimentStatus {
|
|
306
|
+
DRAFT
|
|
307
|
+
RUNNING
|
|
308
|
+
COMPLETED
|
|
309
|
+
PAUSED
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
enum SubscriptionStatus {
|
|
313
|
+
TRIALING
|
|
314
|
+
ACTIVE
|
|
315
|
+
PAST_DUE
|
|
316
|
+
CANCELLED
|
|
317
|
+
EXPIRED
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
enum BillingInterval {
|
|
321
|
+
MONTHLY
|
|
322
|
+
YEARLY
|
|
323
|
+
LIFETIME
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
enum PaymentStatus {
|
|
327
|
+
PENDING
|
|
328
|
+
SUCCEEDED
|
|
329
|
+
FAILED
|
|
330
|
+
REFUNDED
|
|
331
|
+
DISPUTED
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
enum RefundStatus {
|
|
335
|
+
REQUESTED
|
|
336
|
+
APPROVED
|
|
337
|
+
REJECTED
|
|
338
|
+
COMPLETED
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
enum AuditSeverity {
|
|
342
|
+
INFO
|
|
343
|
+
WARNING
|
|
344
|
+
ERROR
|
|
345
|
+
CRITICAL
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
enum AssetType {
|
|
349
|
+
VIDEO
|
|
350
|
+
AUDIO
|
|
351
|
+
IMAGE
|
|
352
|
+
DOCUMENT
|
|
353
|
+
RIVE
|
|
354
|
+
ANIMATION
|
|
355
|
+
OTHER
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
enum TrivitStatus {
|
|
359
|
+
DRAFT
|
|
360
|
+
SCHEDULED
|
|
361
|
+
LIVE
|
|
362
|
+
COMPLETED
|
|
363
|
+
CANCELLED
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
enum AudienceScope {
|
|
367
|
+
EVERYONE
|
|
368
|
+
FOLLOWERS
|
|
369
|
+
NOBODY
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
enum ThemeMode {
|
|
373
|
+
LIGHT
|
|
374
|
+
DARK
|
|
375
|
+
AUTO
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
enum NotificationDigestMode {
|
|
379
|
+
NONE
|
|
380
|
+
DAILY
|
|
381
|
+
WEEKLY
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
enum CollectionType {
|
|
385
|
+
CURATED
|
|
386
|
+
LEARNING_PATH
|
|
387
|
+
ONBOARDING_BUNDLE
|
|
388
|
+
REVISION_PLAYLIST
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
enum CollectionItemType {
|
|
392
|
+
QUIZ
|
|
393
|
+
FLASHCARD_SET
|
|
394
|
+
VIDEO
|
|
395
|
+
LESSON
|
|
396
|
+
EXAM
|
|
397
|
+
COURSE
|
|
398
|
+
RESOURCE
|
|
399
|
+
TRIVIT
|
|
400
|
+
LIVE_SESSION
|
|
401
|
+
COMMUNITY_RESOURCE
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
enum PollStatus {
|
|
405
|
+
DRAFT
|
|
406
|
+
ACTIVE
|
|
407
|
+
CLOSED
|
|
408
|
+
ARCHIVED
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
enum PetElement {
|
|
412
|
+
FIRE
|
|
413
|
+
WATER
|
|
414
|
+
EARTH
|
|
415
|
+
AIR
|
|
416
|
+
MYTH
|
|
417
|
+
LIGHTNING
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
enum PetActionType {
|
|
421
|
+
FEED
|
|
422
|
+
PLAY
|
|
423
|
+
REST
|
|
424
|
+
TRAIN
|
|
425
|
+
BATTLE
|
|
426
|
+
EXPLORE
|
|
427
|
+
CHEER
|
|
428
|
+
HATCH
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
enum PromotionType {
|
|
432
|
+
PERCENT
|
|
433
|
+
FIXED_AMOUNT
|
|
434
|
+
TRIAL_EXTENSION
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
enum SandboxStatus {
|
|
438
|
+
RUNNING
|
|
439
|
+
STOPPED
|
|
440
|
+
ARCHIVED
|
|
441
|
+
FAILED
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
enum SandboxPromotionStatus {
|
|
445
|
+
PENDING
|
|
446
|
+
COMPLETED
|
|
447
|
+
ROLLED_BACK
|
|
448
|
+
FAILED
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
enum AchievementRarity {
|
|
452
|
+
COMMON
|
|
453
|
+
RARE
|
|
454
|
+
EPIC
|
|
455
|
+
LEGENDARY
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
enum AchievementScope {
|
|
459
|
+
PLATFORM
|
|
460
|
+
GAME
|
|
461
|
+
FLASHCARD
|
|
462
|
+
EXAM
|
|
463
|
+
LESSON
|
|
464
|
+
PROFILE
|
|
465
|
+
COMMUNITY
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
enum RewardScope {
|
|
469
|
+
GLOBAL_GAME
|
|
470
|
+
EXAM
|
|
471
|
+
LESSON
|
|
472
|
+
FLASHCARD
|
|
473
|
+
SEASONAL_EVENT
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
enum RewardStatus {
|
|
477
|
+
DRAFT
|
|
478
|
+
ACTIVE
|
|
479
|
+
SCHEDULED
|
|
480
|
+
ARCHIVED
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
enum AntiCheatSeverity {
|
|
484
|
+
LOW
|
|
485
|
+
MEDIUM
|
|
486
|
+
HIGH
|
|
487
|
+
CRITICAL
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
enum AntiCheatStatus {
|
|
491
|
+
OPEN
|
|
492
|
+
REVIEWED
|
|
493
|
+
VALID
|
|
494
|
+
INVALID
|
|
495
|
+
DISMISSED
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
enum CalendarEntryType {
|
|
499
|
+
LESSON
|
|
500
|
+
TASK
|
|
501
|
+
FLASHCARD
|
|
502
|
+
TUTORING
|
|
503
|
+
TEST
|
|
504
|
+
ACTIVITY
|
|
505
|
+
EVENT
|
|
506
|
+
FREE
|
|
507
|
+
REVISION
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
enum CalendarEntryStatus {
|
|
511
|
+
PLANNED
|
|
512
|
+
COMPLETED
|
|
513
|
+
CANCELLED
|
|
514
|
+
SKIPPED
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
enum BackupType {
|
|
518
|
+
FULL
|
|
519
|
+
DATABASE
|
|
520
|
+
MEDIA
|
|
521
|
+
CONFIG
|
|
522
|
+
ARCHIVE
|
|
523
|
+
INCREMENTAL
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
enum LobbyMode {
|
|
527
|
+
COMPETITIVE
|
|
528
|
+
CASUAL
|
|
529
|
+
MINIGAME
|
|
530
|
+
PRIVATE_PRACTICE
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
enum GameServerStatus {
|
|
534
|
+
HEALTHY
|
|
535
|
+
WARNING
|
|
536
|
+
OFFLINE
|
|
537
|
+
MAINTENANCE
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
model Account {
|
|
541
|
+
id String @id @default(cuid())
|
|
542
|
+
userId Int
|
|
543
|
+
provider String
|
|
544
|
+
refresh_token String?
|
|
545
|
+
access_token String?
|
|
546
|
+
expires_at Int?
|
|
547
|
+
token_type String?
|
|
548
|
+
scope String?
|
|
549
|
+
id_token String?
|
|
550
|
+
session_state String?
|
|
551
|
+
|
|
552
|
+
accountId String
|
|
553
|
+
providerId String?
|
|
554
|
+
accessToken String?
|
|
555
|
+
refreshToken String?
|
|
556
|
+
idToken String?
|
|
557
|
+
accessTokenExpiresAt DateTime?
|
|
558
|
+
refreshTokenExpiresAt DateTime?
|
|
559
|
+
password String?
|
|
560
|
+
createdAt DateTime @default(now())
|
|
561
|
+
updatedAt DateTime @updatedAt
|
|
562
|
+
|
|
563
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
564
|
+
|
|
565
|
+
@@unique([provider, providerId])
|
|
566
|
+
@@index([userId])
|
|
567
|
+
@@map("account")
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
model Session {
|
|
571
|
+
id String @id @default(cuid())
|
|
572
|
+
userId Int
|
|
573
|
+
expiresAt DateTime
|
|
574
|
+
token String
|
|
575
|
+
createdAt DateTime @default(now())
|
|
576
|
+
updatedAt DateTime @updatedAt
|
|
577
|
+
ipAddress String?
|
|
578
|
+
userAgent String?
|
|
579
|
+
impersonatedBy String?
|
|
580
|
+
deviceName String?
|
|
581
|
+
location String?
|
|
582
|
+
isCurrent Boolean @default(false)
|
|
583
|
+
|
|
584
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
585
|
+
|
|
586
|
+
@@unique([token])
|
|
587
|
+
@@index([userId])
|
|
588
|
+
@@map("session")
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
model VerificationToken {
|
|
592
|
+
identifier String
|
|
593
|
+
token String @unique
|
|
594
|
+
expires DateTime
|
|
595
|
+
|
|
596
|
+
@@unique([identifier, token])
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
model Verification {
|
|
600
|
+
id String @id
|
|
601
|
+
identifier String
|
|
602
|
+
value String
|
|
603
|
+
expiresAt DateTime
|
|
604
|
+
createdAt DateTime @default(now())
|
|
605
|
+
updatedAt DateTime @updatedAt
|
|
606
|
+
|
|
607
|
+
@@index([identifier])
|
|
608
|
+
@@map("verification")
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
model Jwks {
|
|
612
|
+
id Int @id @default(autoincrement())
|
|
613
|
+
publicKey String
|
|
614
|
+
privateKey String
|
|
615
|
+
createdAt DateTime
|
|
616
|
+
expiresAt DateTime?
|
|
617
|
+
|
|
618
|
+
@@map("jwks")
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
model WebsiteStatus {
|
|
622
|
+
id String @id @default("singleton")
|
|
623
|
+
maintenance Boolean @default(false)
|
|
624
|
+
temporaryDown Boolean @default(false)
|
|
625
|
+
bannerMessage String?
|
|
626
|
+
statusCode WebsiteStatusCode @default(OPERATIONAL)
|
|
627
|
+
lastChecked DateTime?
|
|
628
|
+
createdAt DateTime @default(now())
|
|
629
|
+
updatedAt DateTime @updatedAt
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
model News {
|
|
633
|
+
id String @id @default(cuid())
|
|
634
|
+
title String
|
|
635
|
+
slug String? @unique
|
|
636
|
+
content String
|
|
637
|
+
excerpt String?
|
|
638
|
+
coverImage String?
|
|
639
|
+
category String?
|
|
640
|
+
visibility Visibility @default(PUBLIC)
|
|
641
|
+
status PublicationStatus @default(DRAFT)
|
|
642
|
+
published Boolean @default(false)
|
|
643
|
+
publishedAt DateTime?
|
|
644
|
+
createdAt DateTime @default(now())
|
|
645
|
+
updatedAt DateTime @updatedAt
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
model User {
|
|
649
|
+
id Int @id @default(autoincrement())
|
|
650
|
+
name String?
|
|
651
|
+
email String? @unique
|
|
652
|
+
password String?
|
|
653
|
+
emailVerified Boolean?
|
|
654
|
+
image String?
|
|
655
|
+
role String @default("USER")
|
|
656
|
+
status UserStatus @default(ACTIVE)
|
|
657
|
+
username String? @unique
|
|
658
|
+
displayUsername String?
|
|
659
|
+
bio String?
|
|
660
|
+
headline String?
|
|
661
|
+
pronunciation String?
|
|
662
|
+
academicLevel String?
|
|
663
|
+
timezone String?
|
|
664
|
+
location String?
|
|
665
|
+
phone String?
|
|
666
|
+
website String?
|
|
667
|
+
banned Boolean? @default(false)
|
|
668
|
+
banReason String?
|
|
669
|
+
banExpires DateTime?
|
|
670
|
+
lastSeenAt DateTime?
|
|
671
|
+
createdAt DateTime @default(now())
|
|
672
|
+
updatedAt DateTime @updatedAt
|
|
673
|
+
|
|
674
|
+
accounts Account[]
|
|
675
|
+
sessions Session[]
|
|
676
|
+
quizzes Quiz[]
|
|
677
|
+
quizAttempts QuizAttempt[]
|
|
678
|
+
gameResults GameResult[]
|
|
679
|
+
hostedLobbies Lobby[] @relation("HostedLobbies")
|
|
680
|
+
participants Participant[]
|
|
681
|
+
statistics Statistics?
|
|
682
|
+
statisticsWeekly StatisticsWeeklyReport[]
|
|
683
|
+
flashcardSets FlashcardSet[]
|
|
684
|
+
flashcardStudySessions FlashcardStudySession[]
|
|
685
|
+
flashcardReviews FlashcardReview[]
|
|
686
|
+
coursesAuthored Course[] @relation("CourseAuthor")
|
|
687
|
+
courseEnrollments CourseEnrollment[]
|
|
688
|
+
lessonsAuthored Lesson[] @relation("LessonAuthor")
|
|
689
|
+
lessonProgress LessonProgress[]
|
|
690
|
+
videosAuthored Video[] @relation("VideoAuthor")
|
|
691
|
+
videoProgress VideoProgress[]
|
|
692
|
+
examSessions ExamSession[]
|
|
693
|
+
tutorProfile TutorProfile?
|
|
694
|
+
studentProfile StudentProfile?
|
|
695
|
+
tutorBookingsAsTutor TutorBooking[] @relation("TutorBookings")
|
|
696
|
+
tutorBookingsAsStudent TutorBooking[] @relation("StudentBookings")
|
|
697
|
+
tutoringSessionsAsTutor TutoringSession[] @relation("TutorSessions")
|
|
698
|
+
tutoringSessionAttendees TutoringSessionAttendee[]
|
|
699
|
+
tutorReviewsWritten TutorReview[] @relation("TutorReviewAuthor")
|
|
700
|
+
tutorReviewsReceived TutorReview[] @relation("TutorReviewTarget")
|
|
701
|
+
classroomsOwned Classroom[] @relation("ClassroomOwner")
|
|
702
|
+
classroomEnrollments ClassroomEnrollment[]
|
|
703
|
+
assignmentsAuthored Assignment[] @relation("AssignmentAuthor")
|
|
704
|
+
assignmentSubmissions AssignmentSubmission[]
|
|
705
|
+
conversationsCreated Conversation[] @relation("ConversationCreator")
|
|
706
|
+
conversationParticipants ConversationParticipant[]
|
|
707
|
+
messagesSent Message[] @relation("UserMessages")
|
|
708
|
+
announcements Announcement[] @relation("AnnouncementAuthor")
|
|
709
|
+
announcementRecipients AnnouncementRecipient[]
|
|
710
|
+
notifications Notification[]
|
|
711
|
+
notificationPreference NotificationPreference?
|
|
712
|
+
supportTickets SupportTicket[] @relation("SupportTicketRequester")
|
|
713
|
+
assignedSupportTickets SupportTicket[] @relation("SupportTicketAssignee")
|
|
714
|
+
supportConversations SupportConversation[] @relation("SupportConversationRequester")
|
|
715
|
+
supportAgentConversations SupportConversation[] @relation("SupportConversationAgent")
|
|
716
|
+
supportMessages SupportMessage[] @relation("SupportMessageAuthor")
|
|
717
|
+
communitiesOwned Community[] @relation("CommunityOwner")
|
|
718
|
+
communityMemberships CommunityMembership[]
|
|
719
|
+
communityPosts CommunityPost[]
|
|
720
|
+
communityReplies CommunityReply[]
|
|
721
|
+
communityEventsHosted CommunityEvent[] @relation("CommunityEventHost")
|
|
722
|
+
feedback Feedback[]
|
|
723
|
+
subscriptions UserSubscription[]
|
|
724
|
+
paymentTransactions PaymentTransaction[]
|
|
725
|
+
refundRequests RefundRequest[] @relation("RefundRequester")
|
|
726
|
+
userEvents UserActivityEvent[]
|
|
727
|
+
hostedGames Game[] @relation("HostedGames")
|
|
728
|
+
hostedTrivits TrivitEvent[] @relation("HostedTrivits")
|
|
729
|
+
trivitParticipants TrivitParticipant[]
|
|
730
|
+
roleAssignments UserRoleAssignment[]
|
|
731
|
+
auditLogs AuditLog[]
|
|
732
|
+
resourceFolders ResourceFolder[]
|
|
733
|
+
resources ResourceItem[]
|
|
734
|
+
tutorPaymentMethods TutorPaymentMethod[]
|
|
735
|
+
payoutRequests PayoutRequest[]
|
|
736
|
+
pricingPackages TutorPricingPackage[]
|
|
737
|
+
issuedInvoices TutorInvoice[] @relation("InvoiceIssuer")
|
|
738
|
+
tutorVerificationRequests TutorVerificationRequest[]
|
|
739
|
+
following UserFollow[] @relation("UserFollowFollower")
|
|
740
|
+
followers UserFollow[] @relation("UserFollowFollowing")
|
|
741
|
+
profileReportsFiled ProfileReport[] @relation("ProfileReportReporter")
|
|
742
|
+
profileReportsReceived ProfileReport[] @relation("ProfileReportTarget")
|
|
743
|
+
userAchievements UserAchievement[]
|
|
744
|
+
pinnedContent UserPinnedContent[]
|
|
745
|
+
preferences UserPreference?
|
|
746
|
+
cookieConsent CookieConsentPreference?
|
|
747
|
+
studyCollections StudyCollection[] @relation("StudyCollectionOwner")
|
|
748
|
+
studyCollectionEnrollments StudyCollectionEnrollment[]
|
|
749
|
+
classroomPollsCreated ClassroomPoll[] @relation("ClassroomPollCreator")
|
|
750
|
+
classroomPollResponses ClassroomPollResponse[]
|
|
751
|
+
zaplitProfile ZaplitProfile?
|
|
752
|
+
createdPromotionCodes PromotionCode[] @relation("PromotionCodeCreator")
|
|
753
|
+
createdSandboxes SandboxEnvironment[] @relation("SandboxCreator")
|
|
754
|
+
sandboxPromotions SandboxPromotion[] @relation("SandboxPromotionActor")
|
|
755
|
+
dataSeedRunsTriggered DataSeedRun[] @relation("DataSeedRunActor")
|
|
756
|
+
createdAchievementDefinitions AchievementDefinition[] @relation("AchievementDefinitionCreator")
|
|
757
|
+
examQuestionVersions ExamQuestionVersion[] @relation("ExamQuestionVersionAuthor")
|
|
758
|
+
reviewedAntiCheatFlags ExamAntiCheatFlag[] @relation("ExamAntiCheatReviewer")
|
|
759
|
+
createdCertificationRules CertificationRule[] @relation("CertificationRuleCreator")
|
|
760
|
+
createdRewardRules RewardRule[] @relation("RewardRuleCreator")
|
|
761
|
+
securityTwoFactorMethods SecurityTwoFactorMethod[]
|
|
762
|
+
calendarEntries CalendarEntry[]
|
|
763
|
+
backupRestoreRunsInitiated BackupRestoreRun[] @relation("BackupRestoreInitiator")
|
|
764
|
+
|
|
765
|
+
@@index([role])
|
|
766
|
+
@@index([status])
|
|
767
|
+
@@map("user")
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
model Statistics {
|
|
771
|
+
id String @id @default(cuid())
|
|
772
|
+
userId Int @unique
|
|
773
|
+
totalQuizsCreated Int @default(0)
|
|
774
|
+
totalGamesHosted Int @default(0)
|
|
775
|
+
xpCount Int @default(0)
|
|
776
|
+
timeSpentLearning Int @default(0)
|
|
777
|
+
credits Int @default(0)
|
|
778
|
+
totalWins Int @default(0)
|
|
779
|
+
totalCorrectAnswers Int @default(0)
|
|
780
|
+
totalCrates Int @default(0)
|
|
781
|
+
flashcardSessions Int @default(0)
|
|
782
|
+
examsCompleted Int @default(0)
|
|
783
|
+
tutoringSessions Int @default(0)
|
|
784
|
+
currentStreak Int @default(0)
|
|
785
|
+
longestStreak Int @default(0)
|
|
786
|
+
updatedAt DateTime @updatedAt
|
|
787
|
+
|
|
788
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
789
|
+
|
|
790
|
+
@@map("statistics")
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
model StatisticsWeeklyReport {
|
|
794
|
+
id String @id @default(cuid())
|
|
795
|
+
userId Int
|
|
796
|
+
weekStart DateTime
|
|
797
|
+
weekEnd DateTime?
|
|
798
|
+
totalQuizsCreated Int @default(0)
|
|
799
|
+
totalGamesHosted Int @default(0)
|
|
800
|
+
xpCount Int @default(0)
|
|
801
|
+
timeSpentLearning Int @default(0)
|
|
802
|
+
credits Int @default(0)
|
|
803
|
+
totalWins Int @default(0)
|
|
804
|
+
totalCorrectAnswers Int @default(0)
|
|
805
|
+
totalCrates Int @default(0)
|
|
806
|
+
flashcardSessions Int @default(0)
|
|
807
|
+
examsCompleted Int @default(0)
|
|
808
|
+
createdAt DateTime @default(now())
|
|
809
|
+
|
|
810
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
811
|
+
|
|
812
|
+
@@unique([userId, weekStart])
|
|
813
|
+
@@index([userId, createdAt])
|
|
814
|
+
@@map("statisticsWeeklyReport")
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Data used in public profiles, follows, badges, settings, and collections.
|
|
818
|
+
model UserFollow {
|
|
819
|
+
id String @id @default(cuid())
|
|
820
|
+
followerId Int
|
|
821
|
+
followingId Int
|
|
822
|
+
createdAt DateTime @default(now())
|
|
823
|
+
|
|
824
|
+
follower User @relation("UserFollowFollower", fields: [followerId], references: [id], onDelete: Cascade)
|
|
825
|
+
following User @relation("UserFollowFollowing", fields: [followingId], references: [id], onDelete: Cascade)
|
|
826
|
+
|
|
827
|
+
@@unique([followerId, followingId])
|
|
828
|
+
@@index([followingId, createdAt])
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
model ProfileReport {
|
|
832
|
+
id String @id @default(cuid())
|
|
833
|
+
reporterId Int?
|
|
834
|
+
targetUserId Int
|
|
835
|
+
reason String
|
|
836
|
+
details String?
|
|
837
|
+
status String @default("OPEN")
|
|
838
|
+
metadata Json?
|
|
839
|
+
createdAt DateTime @default(now())
|
|
840
|
+
reviewedAt DateTime?
|
|
841
|
+
|
|
842
|
+
reporter User? @relation("ProfileReportReporter", fields: [reporterId], references: [id], onDelete: SetNull)
|
|
843
|
+
target User @relation("ProfileReportTarget", fields: [targetUserId], references: [id], onDelete: Cascade)
|
|
844
|
+
|
|
845
|
+
@@index([reporterId])
|
|
846
|
+
@@index([targetUserId, status])
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
model AchievementDefinition {
|
|
850
|
+
id String @id @default(cuid())
|
|
851
|
+
key String @unique
|
|
852
|
+
title String
|
|
853
|
+
description String?
|
|
854
|
+
scope AchievementScope @default(PLATFORM)
|
|
855
|
+
rarity AchievementRarity @default(COMMON)
|
|
856
|
+
rewardText String?
|
|
857
|
+
icon String?
|
|
858
|
+
points Int @default(0)
|
|
859
|
+
criteria Json?
|
|
860
|
+
createdById Int?
|
|
861
|
+
active Boolean @default(true)
|
|
862
|
+
createdAt DateTime @default(now())
|
|
863
|
+
updatedAt DateTime @updatedAt
|
|
864
|
+
|
|
865
|
+
createdBy User? @relation("AchievementDefinitionCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
866
|
+
awards UserAchievement[]
|
|
867
|
+
certificationRules CertificationRule[]
|
|
868
|
+
|
|
869
|
+
@@index([scope, active])
|
|
870
|
+
@@index([createdById])
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
model UserAchievement {
|
|
874
|
+
id String @id @default(cuid())
|
|
875
|
+
userId Int
|
|
876
|
+
achievementId String
|
|
877
|
+
progress Int @default(0)
|
|
878
|
+
completed Boolean @default(false)
|
|
879
|
+
completedAt DateTime?
|
|
880
|
+
metadata Json?
|
|
881
|
+
createdAt DateTime @default(now())
|
|
882
|
+
|
|
883
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
884
|
+
achievement AchievementDefinition @relation(fields: [achievementId], references: [id], onDelete: Cascade)
|
|
885
|
+
|
|
886
|
+
@@unique([userId, achievementId])
|
|
887
|
+
@@index([achievementId, completed])
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
model UserPinnedContent {
|
|
891
|
+
id String @id @default(cuid())
|
|
892
|
+
userId Int
|
|
893
|
+
contentType CollectionItemType
|
|
894
|
+
contentId String
|
|
895
|
+
title String?
|
|
896
|
+
rankingMetric String?
|
|
897
|
+
sortOrder Int @default(0)
|
|
898
|
+
metadata Json?
|
|
899
|
+
createdAt DateTime @default(now())
|
|
900
|
+
|
|
901
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
902
|
+
|
|
903
|
+
@@unique([userId, contentType, contentId])
|
|
904
|
+
@@unique([userId, sortOrder])
|
|
905
|
+
@@index([userId, createdAt])
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
model UserPreference {
|
|
909
|
+
id String @id @default(cuid())
|
|
910
|
+
userId Int @unique
|
|
911
|
+
whoCanMessage AudienceScope @default(EVERYONE)
|
|
912
|
+
whoCanInvite AudienceScope @default(EVERYONE)
|
|
913
|
+
whoCanSeeProfile AudienceScope @default(EVERYONE)
|
|
914
|
+
profileVisible Boolean @default(true)
|
|
915
|
+
appearOnline Boolean @default(true)
|
|
916
|
+
showInLeaderboards Boolean @default(true)
|
|
917
|
+
showActivity Boolean @default(true)
|
|
918
|
+
theme ThemeMode @default(DARK)
|
|
919
|
+
accentColor String? @default("yellow")
|
|
920
|
+
reduceMotion Boolean @default(false)
|
|
921
|
+
fontSize Int @default(16)
|
|
922
|
+
showTutorRating Boolean @default(true)
|
|
923
|
+
showStudentCount Boolean @default(true)
|
|
924
|
+
allowDirectMessages Boolean @default(true)
|
|
925
|
+
showLocation Boolean @default(true)
|
|
926
|
+
updatedAt DateTime @updatedAt
|
|
927
|
+
|
|
928
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
model CookieConsentPreference {
|
|
932
|
+
id String @id @default(cuid())
|
|
933
|
+
userId Int @unique
|
|
934
|
+
essential Boolean @default(true)
|
|
935
|
+
analytics Boolean @default(false)
|
|
936
|
+
functional Boolean @default(false)
|
|
937
|
+
marketing Boolean @default(false)
|
|
938
|
+
consentedAt DateTime?
|
|
939
|
+
updatedAt DateTime @updatedAt
|
|
940
|
+
|
|
941
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
model StudyCollection {
|
|
945
|
+
id String @id @default(cuid())
|
|
946
|
+
ownerId Int?
|
|
947
|
+
title String
|
|
948
|
+
slug String? @unique
|
|
949
|
+
description String?
|
|
950
|
+
type CollectionType @default(CURATED)
|
|
951
|
+
visibility Visibility @default(PRIVATE)
|
|
952
|
+
status PublicationStatus @default(DRAFT)
|
|
953
|
+
tag String?
|
|
954
|
+
coverImage String?
|
|
955
|
+
totalItems Int @default(0)
|
|
956
|
+
totalDurationMinutes Int @default(0)
|
|
957
|
+
enrolledCount Int @default(0)
|
|
958
|
+
metadata Json?
|
|
959
|
+
createdAt DateTime @default(now())
|
|
960
|
+
updatedAt DateTime @updatedAt
|
|
961
|
+
|
|
962
|
+
owner User? @relation("StudyCollectionOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
|
963
|
+
items StudyCollectionItem[]
|
|
964
|
+
enrollments StudyCollectionEnrollment[]
|
|
965
|
+
|
|
966
|
+
@@index([ownerId])
|
|
967
|
+
@@index([status, visibility])
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
model StudyCollectionItem {
|
|
971
|
+
id String @id @default(cuid())
|
|
972
|
+
collectionId String
|
|
973
|
+
type CollectionItemType
|
|
974
|
+
contentId String
|
|
975
|
+
title String?
|
|
976
|
+
sortOrder Int @default(0)
|
|
977
|
+
metadata Json?
|
|
978
|
+
|
|
979
|
+
collection StudyCollection @relation(fields: [collectionId], references: [id], onDelete: Cascade)
|
|
980
|
+
|
|
981
|
+
@@unique([collectionId, type, contentId])
|
|
982
|
+
@@unique([collectionId, sortOrder])
|
|
983
|
+
@@index([collectionId])
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
model StudyCollectionEnrollment {
|
|
987
|
+
id String @id @default(cuid())
|
|
988
|
+
collectionId String
|
|
989
|
+
userId Int
|
|
990
|
+
progress Int @default(0)
|
|
991
|
+
currentItemOrder Int?
|
|
992
|
+
startedAt DateTime @default(now())
|
|
993
|
+
completedAt DateTime?
|
|
994
|
+
|
|
995
|
+
collection StudyCollection @relation(fields: [collectionId], references: [id], onDelete: Cascade)
|
|
996
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
997
|
+
|
|
998
|
+
@@unique([collectionId, userId])
|
|
999
|
+
@@index([userId, startedAt])
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// Data used in the Zaplits dashboard.
|
|
1003
|
+
model ZaplitProfile {
|
|
1004
|
+
id String @id @default(cuid())
|
|
1005
|
+
userId Int @unique
|
|
1006
|
+
activePetId String?
|
|
1007
|
+
eggCount Int @default(0)
|
|
1008
|
+
coins Int @default(0)
|
|
1009
|
+
totalXp Int @default(0)
|
|
1010
|
+
createdAt DateTime @default(now())
|
|
1011
|
+
updatedAt DateTime @updatedAt
|
|
1012
|
+
|
|
1013
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1014
|
+
pets ZaplitPet[]
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
model ZaplitPet {
|
|
1018
|
+
id String @id @default(cuid())
|
|
1019
|
+
profileId String
|
|
1020
|
+
name String
|
|
1021
|
+
species String?
|
|
1022
|
+
element PetElement?
|
|
1023
|
+
icon String?
|
|
1024
|
+
level Int @default(1)
|
|
1025
|
+
xp Int @default(0)
|
|
1026
|
+
maxXp Int @default(100)
|
|
1027
|
+
hp Int @default(100)
|
|
1028
|
+
energy Int @default(100)
|
|
1029
|
+
mood Int @default(100)
|
|
1030
|
+
nextLevel Int?
|
|
1031
|
+
quizzesUntilNext Int?
|
|
1032
|
+
isActive Boolean @default(false)
|
|
1033
|
+
metadata Json?
|
|
1034
|
+
unlockedAt DateTime @default(now())
|
|
1035
|
+
lastInteractedAt DateTime?
|
|
1036
|
+
|
|
1037
|
+
profile ZaplitProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
|
1038
|
+
actions ZaplitPetActionLog[]
|
|
1039
|
+
|
|
1040
|
+
@@index([profileId, isActive])
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
model ZaplitPetActionLog {
|
|
1044
|
+
id String @id @default(cuid())
|
|
1045
|
+
petId String
|
|
1046
|
+
action PetActionType
|
|
1047
|
+
deltaXp Int @default(0)
|
|
1048
|
+
deltaHp Int @default(0)
|
|
1049
|
+
deltaEnergy Int @default(0)
|
|
1050
|
+
deltaMood Int @default(0)
|
|
1051
|
+
metadata Json?
|
|
1052
|
+
createdAt DateTime @default(now())
|
|
1053
|
+
|
|
1054
|
+
pet ZaplitPet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
|
1055
|
+
|
|
1056
|
+
@@index([petId, createdAt])
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
model CalendarEntry {
|
|
1060
|
+
id String @id @default(cuid())
|
|
1061
|
+
userId Int
|
|
1062
|
+
title String
|
|
1063
|
+
description String?
|
|
1064
|
+
type CalendarEntryType
|
|
1065
|
+
status CalendarEntryStatus @default(PLANNED)
|
|
1066
|
+
startsAt DateTime
|
|
1067
|
+
endsAt DateTime?
|
|
1068
|
+
subjectName String?
|
|
1069
|
+
location String?
|
|
1070
|
+
room String?
|
|
1071
|
+
notes String?
|
|
1072
|
+
sourceType String?
|
|
1073
|
+
sourceId String?
|
|
1074
|
+
recurringRule String?
|
|
1075
|
+
isAutoGenerated Boolean @default(false)
|
|
1076
|
+
metadata Json?
|
|
1077
|
+
createdAt DateTime @default(now())
|
|
1078
|
+
updatedAt DateTime @updatedAt
|
|
1079
|
+
|
|
1080
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1081
|
+
|
|
1082
|
+
@@index([userId, startsAt])
|
|
1083
|
+
@@index([type, status])
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
model AcademicBoard {
|
|
1087
|
+
id String @id @default(cuid())
|
|
1088
|
+
name String
|
|
1089
|
+
code String @unique
|
|
1090
|
+
countryCode String?
|
|
1091
|
+
description String?
|
|
1092
|
+
createdAt DateTime @default(now())
|
|
1093
|
+
updatedAt DateTime @updatedAt
|
|
1094
|
+
|
|
1095
|
+
courses Course[]
|
|
1096
|
+
exams Exam[]
|
|
1097
|
+
tutorSubjects TutorSubject[]
|
|
1098
|
+
classrooms Classroom[]
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
model Subject {
|
|
1102
|
+
id String @id @default(cuid())
|
|
1103
|
+
name String
|
|
1104
|
+
slug String @unique
|
|
1105
|
+
description String?
|
|
1106
|
+
color String?
|
|
1107
|
+
icon String?
|
|
1108
|
+
createdAt DateTime @default(now())
|
|
1109
|
+
updatedAt DateTime @updatedAt
|
|
1110
|
+
|
|
1111
|
+
courses Course[]
|
|
1112
|
+
lessons Lesson[]
|
|
1113
|
+
videos Video[]
|
|
1114
|
+
quizzes Quiz[]
|
|
1115
|
+
exams Exam[]
|
|
1116
|
+
tutorSubjects TutorSubject[]
|
|
1117
|
+
tutorBookings TutorBooking[]
|
|
1118
|
+
classrooms Classroom[]
|
|
1119
|
+
communities Community[]
|
|
1120
|
+
userEvents UserActivityEvent[]
|
|
1121
|
+
tutoringSessions TutoringSession[]
|
|
1122
|
+
trivitEvents TrivitEvent[]
|
|
1123
|
+
certificationRules CertificationRule[]
|
|
1124
|
+
|
|
1125
|
+
@@unique([name])
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
model Course {
|
|
1129
|
+
id String @id @default(cuid())
|
|
1130
|
+
authorId Int
|
|
1131
|
+
subjectId String?
|
|
1132
|
+
boardId String?
|
|
1133
|
+
title String
|
|
1134
|
+
slug String @unique
|
|
1135
|
+
description String?
|
|
1136
|
+
level CourseLevel?
|
|
1137
|
+
yearGroup String?
|
|
1138
|
+
totalHours Int?
|
|
1139
|
+
totalLessons Int @default(0)
|
|
1140
|
+
totalQuizzes Int @default(0)
|
|
1141
|
+
totalFlashcards Int @default(0)
|
|
1142
|
+
status PublicationStatus @default(DRAFT)
|
|
1143
|
+
visibility Visibility @default(PRIVATE)
|
|
1144
|
+
coverImage String?
|
|
1145
|
+
colorFrom String?
|
|
1146
|
+
colorTo String?
|
|
1147
|
+
metadata Json?
|
|
1148
|
+
publishedAt DateTime?
|
|
1149
|
+
createdAt DateTime @default(now())
|
|
1150
|
+
updatedAt DateTime @updatedAt
|
|
1151
|
+
|
|
1152
|
+
author User @relation("CourseAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
1153
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1154
|
+
board AcademicBoard? @relation(fields: [boardId], references: [id], onDelete: SetNull)
|
|
1155
|
+
topics CourseTopic[]
|
|
1156
|
+
lessons Lesson[]
|
|
1157
|
+
videos Video[]
|
|
1158
|
+
videoPlaylists VideoPlaylist[]
|
|
1159
|
+
quizzes Quiz[]
|
|
1160
|
+
flashcardSets FlashcardSet[]
|
|
1161
|
+
resources ResourceItem[]
|
|
1162
|
+
enrollments CourseEnrollment[]
|
|
1163
|
+
assignments Assignment[]
|
|
1164
|
+
exams Exam[]
|
|
1165
|
+
classrooms Classroom[]
|
|
1166
|
+
|
|
1167
|
+
@@index([authorId])
|
|
1168
|
+
@@index([subjectId])
|
|
1169
|
+
@@index([boardId])
|
|
1170
|
+
@@index([status, visibility])
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
model CourseEnrollment {
|
|
1174
|
+
id String @id @default(cuid())
|
|
1175
|
+
courseId String
|
|
1176
|
+
userId Int
|
|
1177
|
+
status EnrollmentStatus @default(ACTIVE)
|
|
1178
|
+
progress Int @default(0)
|
|
1179
|
+
lessonsLeft Int @default(0)
|
|
1180
|
+
streak Int @default(0)
|
|
1181
|
+
isPinned Boolean @default(false)
|
|
1182
|
+
specMatch Int?
|
|
1183
|
+
specInfo String?
|
|
1184
|
+
lastStudiedAt DateTime?
|
|
1185
|
+
completedAt DateTime?
|
|
1186
|
+
createdAt DateTime @default(now())
|
|
1187
|
+
updatedAt DateTime @updatedAt
|
|
1188
|
+
|
|
1189
|
+
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
|
|
1190
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1191
|
+
|
|
1192
|
+
@@unique([courseId, userId])
|
|
1193
|
+
@@index([userId, status])
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
model CourseTopic {
|
|
1197
|
+
id String @id @default(cuid())
|
|
1198
|
+
courseId String
|
|
1199
|
+
number Int?
|
|
1200
|
+
name String
|
|
1201
|
+
slug String?
|
|
1202
|
+
description String?
|
|
1203
|
+
durationMinutes Int?
|
|
1204
|
+
order Int @default(0)
|
|
1205
|
+
videosCount Int @default(0)
|
|
1206
|
+
quizzesCount Int @default(0)
|
|
1207
|
+
flashcardsCount Int @default(0)
|
|
1208
|
+
lessonsCount Int @default(0)
|
|
1209
|
+
createdAt DateTime @default(now())
|
|
1210
|
+
updatedAt DateTime @updatedAt
|
|
1211
|
+
|
|
1212
|
+
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
|
|
1213
|
+
lessons Lesson[]
|
|
1214
|
+
videos Video[]
|
|
1215
|
+
quizzes Quiz[]
|
|
1216
|
+
exams Exam[]
|
|
1217
|
+
questions Question[]
|
|
1218
|
+
|
|
1219
|
+
@@index([courseId, order])
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
model Lesson {
|
|
1223
|
+
id String @id @default(cuid())
|
|
1224
|
+
authorId Int
|
|
1225
|
+
courseId String?
|
|
1226
|
+
topicId String?
|
|
1227
|
+
subjectId String?
|
|
1228
|
+
title String
|
|
1229
|
+
slug String? @unique
|
|
1230
|
+
description String?
|
|
1231
|
+
type LessonType @default(MIXED)
|
|
1232
|
+
status PublicationStatus @default(DRAFT)
|
|
1233
|
+
visibility Visibility @default(PRIVATE)
|
|
1234
|
+
durationMinutes Int?
|
|
1235
|
+
progressSummary Int @default(0)
|
|
1236
|
+
learningOutcomes Json?
|
|
1237
|
+
downloadableNotes Json?
|
|
1238
|
+
relatedFlashcards Json?
|
|
1239
|
+
explainedByName String?
|
|
1240
|
+
explainedByAvatar String?
|
|
1241
|
+
metadata Json?
|
|
1242
|
+
createdAt DateTime @default(now())
|
|
1243
|
+
updatedAt DateTime @updatedAt
|
|
1244
|
+
publishedAt DateTime?
|
|
1245
|
+
|
|
1246
|
+
author User? @relation("LessonAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
1247
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1248
|
+
topic CourseTopic? @relation(fields: [topicId], references: [id], onDelete: SetNull)
|
|
1249
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1250
|
+
steps LessonStep[]
|
|
1251
|
+
versions LessonVersion[]
|
|
1252
|
+
assets LessonAsset[]
|
|
1253
|
+
progress LessonProgress[]
|
|
1254
|
+
videos Video[]
|
|
1255
|
+
resources ResourceItem[]
|
|
1256
|
+
quizzes Quiz[]
|
|
1257
|
+
exams Exam[]
|
|
1258
|
+
assignments Assignment[]
|
|
1259
|
+
|
|
1260
|
+
@@index([authorId])
|
|
1261
|
+
@@index([courseId])
|
|
1262
|
+
@@index([topicId])
|
|
1263
|
+
@@index([subjectId])
|
|
1264
|
+
@@index([status, visibility])
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
model LessonStep {
|
|
1268
|
+
id String @id @default(cuid())
|
|
1269
|
+
lessonId String
|
|
1270
|
+
order Int @default(0)
|
|
1271
|
+
type LessonStepType
|
|
1272
|
+
title String
|
|
1273
|
+
durationMinutes Int?
|
|
1274
|
+
isRequired Boolean @default(true)
|
|
1275
|
+
content Json
|
|
1276
|
+
metadata Json?
|
|
1277
|
+
createdAt DateTime @default(now())
|
|
1278
|
+
updatedAt DateTime @updatedAt
|
|
1279
|
+
|
|
1280
|
+
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
|
1281
|
+
|
|
1282
|
+
@@unique([lessonId, order])
|
|
1283
|
+
@@index([lessonId, type])
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
model LessonVersion {
|
|
1287
|
+
id String @id @default(cuid())
|
|
1288
|
+
lessonId String
|
|
1289
|
+
versionLabel String
|
|
1290
|
+
notes String?
|
|
1291
|
+
snapshot Json
|
|
1292
|
+
createdById Int?
|
|
1293
|
+
createdAt DateTime @default(now())
|
|
1294
|
+
|
|
1295
|
+
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
|
1296
|
+
|
|
1297
|
+
@@index([lessonId, createdAt])
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
model LessonAsset {
|
|
1301
|
+
id String @id @default(cuid())
|
|
1302
|
+
lessonId String
|
|
1303
|
+
type AssetType
|
|
1304
|
+
name String
|
|
1305
|
+
url String
|
|
1306
|
+
mimeType String?
|
|
1307
|
+
sizeBytes Int?
|
|
1308
|
+
metadata Json?
|
|
1309
|
+
uploadedById Int?
|
|
1310
|
+
createdAt DateTime @default(now())
|
|
1311
|
+
|
|
1312
|
+
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
|
1313
|
+
|
|
1314
|
+
@@index([lessonId, type])
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
model LessonProgress {
|
|
1318
|
+
id String @id @default(cuid())
|
|
1319
|
+
lessonId String
|
|
1320
|
+
userId Int
|
|
1321
|
+
currentStepIndex Int @default(0)
|
|
1322
|
+
xp Int @default(0)
|
|
1323
|
+
streak Int @default(0)
|
|
1324
|
+
maxStreak Int @default(0)
|
|
1325
|
+
correctAnswers Int @default(0)
|
|
1326
|
+
incorrectAnswers Int @default(0)
|
|
1327
|
+
hintsUsed Int @default(0)
|
|
1328
|
+
progress Int @default(0)
|
|
1329
|
+
startedAt DateTime @default(now())
|
|
1330
|
+
completedAt DateTime?
|
|
1331
|
+
updatedAt DateTime @updatedAt
|
|
1332
|
+
|
|
1333
|
+
lesson Lesson @relation(fields: [lessonId], references: [id], onDelete: Cascade)
|
|
1334
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1335
|
+
|
|
1336
|
+
@@unique([lessonId, userId])
|
|
1337
|
+
@@index([userId, updatedAt])
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
model Video {
|
|
1341
|
+
id String @id @default(cuid())
|
|
1342
|
+
authorId Int
|
|
1343
|
+
courseId String?
|
|
1344
|
+
topicId String?
|
|
1345
|
+
subjectId String?
|
|
1346
|
+
lessonId String?
|
|
1347
|
+
title String
|
|
1348
|
+
description String?
|
|
1349
|
+
status PublicationStatus @default(DRAFT)
|
|
1350
|
+
visibility Visibility @default(PRIVATE)
|
|
1351
|
+
difficulty VideoDifficulty?
|
|
1352
|
+
url String?
|
|
1353
|
+
thumbnail String?
|
|
1354
|
+
durationSeconds Int @default(0)
|
|
1355
|
+
transcript String?
|
|
1356
|
+
views Int @default(0)
|
|
1357
|
+
likes Int @default(0)
|
|
1358
|
+
isFeatured Boolean @default(false)
|
|
1359
|
+
hasNotes Boolean @default(false)
|
|
1360
|
+
hasQuiz Boolean @default(false)
|
|
1361
|
+
tags Json?
|
|
1362
|
+
metadata Json?
|
|
1363
|
+
publishedAt DateTime?
|
|
1364
|
+
createdAt DateTime @default(now())
|
|
1365
|
+
updatedAt DateTime @updatedAt
|
|
1366
|
+
|
|
1367
|
+
author User @relation("VideoAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
1368
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1369
|
+
topic CourseTopic? @relation(fields: [topicId], references: [id], onDelete: SetNull)
|
|
1370
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1371
|
+
lesson Lesson? @relation(fields: [lessonId], references: [id], onDelete: SetNull)
|
|
1372
|
+
chapters VideoChapter[]
|
|
1373
|
+
playlists VideoPlaylistItem[]
|
|
1374
|
+
progress VideoProgress[]
|
|
1375
|
+
|
|
1376
|
+
@@index([authorId])
|
|
1377
|
+
@@index([courseId])
|
|
1378
|
+
@@index([subjectId])
|
|
1379
|
+
@@index([status, visibility])
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
model VideoChapter {
|
|
1383
|
+
id String @id @default(cuid())
|
|
1384
|
+
videoId String
|
|
1385
|
+
title String
|
|
1386
|
+
timeSecond Int
|
|
1387
|
+
order Int @default(0)
|
|
1388
|
+
|
|
1389
|
+
video Video @relation(fields: [videoId], references: [id], onDelete: Cascade)
|
|
1390
|
+
|
|
1391
|
+
@@unique([videoId, order])
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
model VideoPlaylist {
|
|
1395
|
+
id String @id @default(cuid())
|
|
1396
|
+
title String
|
|
1397
|
+
description String?
|
|
1398
|
+
courseId String?
|
|
1399
|
+
thumbnail String?
|
|
1400
|
+
totalDuration Int @default(0)
|
|
1401
|
+
createdAt DateTime @default(now())
|
|
1402
|
+
updatedAt DateTime @updatedAt
|
|
1403
|
+
|
|
1404
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1405
|
+
items VideoPlaylistItem[]
|
|
1406
|
+
|
|
1407
|
+
@@index([courseId])
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
model VideoPlaylistItem {
|
|
1411
|
+
id String @id @default(cuid())
|
|
1412
|
+
playlistId String
|
|
1413
|
+
videoId String
|
|
1414
|
+
order Int @default(0)
|
|
1415
|
+
|
|
1416
|
+
playlist VideoPlaylist @relation(fields: [playlistId], references: [id], onDelete: Cascade)
|
|
1417
|
+
video Video @relation(fields: [videoId], references: [id], onDelete: Cascade)
|
|
1418
|
+
|
|
1419
|
+
@@unique([playlistId, videoId])
|
|
1420
|
+
@@unique([playlistId, order])
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
model VideoProgress {
|
|
1424
|
+
id String @id @default(cuid())
|
|
1425
|
+
videoId String
|
|
1426
|
+
userId Int
|
|
1427
|
+
watchedSeconds Int @default(0)
|
|
1428
|
+
progress Int @default(0)
|
|
1429
|
+
isBookmarked Boolean @default(false)
|
|
1430
|
+
isLiked Boolean @default(false)
|
|
1431
|
+
completedAt DateTime?
|
|
1432
|
+
updatedAt DateTime @updatedAt
|
|
1433
|
+
|
|
1434
|
+
video Video @relation(fields: [videoId], references: [id], onDelete: Cascade)
|
|
1435
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1436
|
+
|
|
1437
|
+
@@unique([videoId, userId])
|
|
1438
|
+
@@index([userId, updatedAt])
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
model Quiz {
|
|
1442
|
+
id String @id @default(cuid())
|
|
1443
|
+
title String
|
|
1444
|
+
slug String? @unique
|
|
1445
|
+
description String?
|
|
1446
|
+
isPublic Boolean @default(false)
|
|
1447
|
+
visibility Visibility @default(PRIVATE)
|
|
1448
|
+
status PublicationStatus @default(DRAFT)
|
|
1449
|
+
coverImage String?
|
|
1450
|
+
subjectId String?
|
|
1451
|
+
courseId String?
|
|
1452
|
+
topicId String?
|
|
1453
|
+
lessonId String?
|
|
1454
|
+
boardCode String?
|
|
1455
|
+
level CourseLevel?
|
|
1456
|
+
category String?
|
|
1457
|
+
estimatedDurationMinutes Int?
|
|
1458
|
+
tags Json?
|
|
1459
|
+
createdAt DateTime @default(now())
|
|
1460
|
+
updatedAt DateTime @updatedAt
|
|
1461
|
+
authorId Int
|
|
1462
|
+
|
|
1463
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
1464
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1465
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1466
|
+
topic CourseTopic? @relation(fields: [topicId], references: [id], onDelete: SetNull)
|
|
1467
|
+
lesson Lesson? @relation(fields: [lessonId], references: [id], onDelete: SetNull)
|
|
1468
|
+
questions Question[]
|
|
1469
|
+
games Game[]
|
|
1470
|
+
lobbies Lobby[]
|
|
1471
|
+
attempts QuizAttempt[]
|
|
1472
|
+
|
|
1473
|
+
@@index([authorId])
|
|
1474
|
+
@@index([subjectId])
|
|
1475
|
+
@@index([courseId])
|
|
1476
|
+
@@index([topicId])
|
|
1477
|
+
@@index([lessonId])
|
|
1478
|
+
@@index([status, visibility])
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
model Question {
|
|
1482
|
+
id String @id @default(cuid())
|
|
1483
|
+
quizId String
|
|
1484
|
+
topicId String?
|
|
1485
|
+
text String
|
|
1486
|
+
imageUrl String?
|
|
1487
|
+
explanation String?
|
|
1488
|
+
hint String?
|
|
1489
|
+
timeLimit Int @default(30)
|
|
1490
|
+
points Int @default(100)
|
|
1491
|
+
sortOrder Int @default(0)
|
|
1492
|
+
type QuestionType @default(MULTIPLE_CHOICE)
|
|
1493
|
+
metadata Json?
|
|
1494
|
+
|
|
1495
|
+
quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade)
|
|
1496
|
+
topic CourseTopic? @relation(fields: [topicId], references: [id], onDelete: SetNull)
|
|
1497
|
+
options QuestionOption[]
|
|
1498
|
+
answers QuizAttemptAnswer[]
|
|
1499
|
+
|
|
1500
|
+
@@index([quizId, sortOrder])
|
|
1501
|
+
@@index([topicId])
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
model QuestionOption {
|
|
1505
|
+
id String @id @default(cuid())
|
|
1506
|
+
questionId String
|
|
1507
|
+
text String
|
|
1508
|
+
isCorrect Boolean
|
|
1509
|
+
explanation String?
|
|
1510
|
+
mediaUrl String?
|
|
1511
|
+
sortOrder Int @default(0)
|
|
1512
|
+
|
|
1513
|
+
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
1514
|
+
|
|
1515
|
+
@@index([questionId, sortOrder])
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
model QuizAttempt {
|
|
1519
|
+
id String @id @default(cuid())
|
|
1520
|
+
quizId String
|
|
1521
|
+
userId Int
|
|
1522
|
+
score Int @default(0)
|
|
1523
|
+
correctAnswers Int @default(0)
|
|
1524
|
+
totalQuestions Int @default(0)
|
|
1525
|
+
accuracy Float @default(0)
|
|
1526
|
+
durationSeconds Int?
|
|
1527
|
+
startedAt DateTime @default(now())
|
|
1528
|
+
completedAt DateTime?
|
|
1529
|
+
|
|
1530
|
+
quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade)
|
|
1531
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1532
|
+
answers QuizAttemptAnswer[]
|
|
1533
|
+
|
|
1534
|
+
@@index([quizId, completedAt])
|
|
1535
|
+
@@index([userId, completedAt])
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
model QuizAttemptAnswer {
|
|
1539
|
+
id String @id @default(cuid())
|
|
1540
|
+
attemptId String
|
|
1541
|
+
questionId String
|
|
1542
|
+
answerText String?
|
|
1543
|
+
selectedIndexes Json?
|
|
1544
|
+
isCorrect Boolean @default(false)
|
|
1545
|
+
pointsEarned Int @default(0)
|
|
1546
|
+
timeTakenSecond Int?
|
|
1547
|
+
|
|
1548
|
+
attempt QuizAttempt @relation(fields: [attemptId], references: [id], onDelete: Cascade)
|
|
1549
|
+
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
1550
|
+
|
|
1551
|
+
@@index([attemptId])
|
|
1552
|
+
@@index([questionId])
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
model FlashcardSet {
|
|
1556
|
+
id String @id @default(cuid())
|
|
1557
|
+
title String
|
|
1558
|
+
description String?
|
|
1559
|
+
subjectId String?
|
|
1560
|
+
courseId String?
|
|
1561
|
+
visibility Visibility @default(PRIVATE)
|
|
1562
|
+
status PublicationStatus @default(DRAFT)
|
|
1563
|
+
authorId Int
|
|
1564
|
+
createdAt DateTime @default(now())
|
|
1565
|
+
updatedAt DateTime @updatedAt
|
|
1566
|
+
|
|
1567
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
1568
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1569
|
+
subdecks FlashcardSubdeck[]
|
|
1570
|
+
studySessions FlashcardStudySession[]
|
|
1571
|
+
|
|
1572
|
+
@@index([authorId])
|
|
1573
|
+
@@index([courseId])
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
model FlashcardSubdeck {
|
|
1577
|
+
id String @id @default(cuid())
|
|
1578
|
+
title String
|
|
1579
|
+
setId String
|
|
1580
|
+
parentId String?
|
|
1581
|
+
sortOrder Int @default(0)
|
|
1582
|
+
createdAt DateTime @default(now())
|
|
1583
|
+
updatedAt DateTime @updatedAt
|
|
1584
|
+
|
|
1585
|
+
flashcardSet FlashcardSet @relation(fields: [setId], references: [id], onDelete: Cascade)
|
|
1586
|
+
parent FlashcardSubdeck? @relation("SubdeckToSubdeck", fields: [parentId], references: [id], onDelete: SetNull)
|
|
1587
|
+
children FlashcardSubdeck[] @relation("SubdeckToSubdeck")
|
|
1588
|
+
flashcards Flashcard[]
|
|
1589
|
+
|
|
1590
|
+
@@index([setId, sortOrder])
|
|
1591
|
+
@@index([parentId])
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
model Flashcard {
|
|
1595
|
+
id String @id @default(cuid())
|
|
1596
|
+
subdeckId String
|
|
1597
|
+
question String
|
|
1598
|
+
answer String
|
|
1599
|
+
explanation String?
|
|
1600
|
+
hint String?
|
|
1601
|
+
imageUrl String?
|
|
1602
|
+
tags Json?
|
|
1603
|
+
easeFactor Float @default(2.5)
|
|
1604
|
+
intervalDays Int @default(0)
|
|
1605
|
+
repetitions Int @default(0)
|
|
1606
|
+
nextReviewAt DateTime?
|
|
1607
|
+
createdAt DateTime @default(now())
|
|
1608
|
+
updatedAt DateTime @updatedAt
|
|
1609
|
+
|
|
1610
|
+
subdeck FlashcardSubdeck @relation(fields: [subdeckId], references: [id], onDelete: Cascade)
|
|
1611
|
+
reviews FlashcardReview[]
|
|
1612
|
+
|
|
1613
|
+
@@index([subdeckId])
|
|
1614
|
+
@@index([nextReviewAt])
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
model FlashcardStudySession {
|
|
1618
|
+
id String @id @default(cuid())
|
|
1619
|
+
setId String
|
|
1620
|
+
userId Int
|
|
1621
|
+
cardsStudied Int @default(0)
|
|
1622
|
+
correctCount Int @default(0)
|
|
1623
|
+
durationSecond Int @default(0)
|
|
1624
|
+
startedAt DateTime @default(now())
|
|
1625
|
+
endedAt DateTime?
|
|
1626
|
+
|
|
1627
|
+
set FlashcardSet @relation(fields: [setId], references: [id], onDelete: Cascade)
|
|
1628
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1629
|
+
|
|
1630
|
+
@@index([setId])
|
|
1631
|
+
@@index([userId, startedAt])
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
model FlashcardReview {
|
|
1635
|
+
id String @id @default(cuid())
|
|
1636
|
+
flashcardId String
|
|
1637
|
+
userId Int
|
|
1638
|
+
rating Int
|
|
1639
|
+
reviewedAt DateTime @default(now())
|
|
1640
|
+
|
|
1641
|
+
flashcard Flashcard @relation(fields: [flashcardId], references: [id], onDelete: Cascade)
|
|
1642
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1643
|
+
|
|
1644
|
+
@@index([flashcardId, reviewedAt])
|
|
1645
|
+
@@index([userId, reviewedAt])
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
model Exam {
|
|
1649
|
+
id String @id @default(cuid())
|
|
1650
|
+
title String
|
|
1651
|
+
slug String? @unique
|
|
1652
|
+
description String?
|
|
1653
|
+
subjectId String?
|
|
1654
|
+
boardId String?
|
|
1655
|
+
courseId String?
|
|
1656
|
+
lessonId String?
|
|
1657
|
+
topicId String?
|
|
1658
|
+
level CourseLevel?
|
|
1659
|
+
paper String?
|
|
1660
|
+
status ExamStatus @default(DRAFT)
|
|
1661
|
+
timeLimitMinutes Int?
|
|
1662
|
+
totalMarks Int @default(0)
|
|
1663
|
+
instructions String?
|
|
1664
|
+
metadata Json?
|
|
1665
|
+
createdById Int?
|
|
1666
|
+
createdAt DateTime @default(now())
|
|
1667
|
+
updatedAt DateTime @updatedAt
|
|
1668
|
+
publishedAt DateTime?
|
|
1669
|
+
|
|
1670
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1671
|
+
board AcademicBoard? @relation(fields: [boardId], references: [id], onDelete: SetNull)
|
|
1672
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1673
|
+
lesson Lesson? @relation(fields: [lessonId], references: [id], onDelete: SetNull)
|
|
1674
|
+
topic CourseTopic? @relation(fields: [topicId], references: [id], onDelete: SetNull)
|
|
1675
|
+
sections ExamSection[]
|
|
1676
|
+
questions ExamQuestion[]
|
|
1677
|
+
sessions ExamSession[]
|
|
1678
|
+
certificationRules CertificationRule[]
|
|
1679
|
+
|
|
1680
|
+
@@index([subjectId])
|
|
1681
|
+
@@index([boardId])
|
|
1682
|
+
@@index([courseId])
|
|
1683
|
+
@@index([status])
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
model ExamSection {
|
|
1687
|
+
id String @id @default(cuid())
|
|
1688
|
+
examId String
|
|
1689
|
+
title String
|
|
1690
|
+
instructions String?
|
|
1691
|
+
sortOrder Int @default(0)
|
|
1692
|
+
marks Int @default(0)
|
|
1693
|
+
|
|
1694
|
+
exam Exam @relation(fields: [examId], references: [id], onDelete: Cascade)
|
|
1695
|
+
questions ExamQuestion[]
|
|
1696
|
+
|
|
1697
|
+
@@unique([examId, sortOrder])
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
model ExamQuestion {
|
|
1701
|
+
id String @id @default(cuid())
|
|
1702
|
+
examId String
|
|
1703
|
+
sectionId String?
|
|
1704
|
+
prompt String
|
|
1705
|
+
questionNumber Int?
|
|
1706
|
+
marks Int @default(1)
|
|
1707
|
+
expectedAnswer String?
|
|
1708
|
+
workedSolution String?
|
|
1709
|
+
markScheme Json?
|
|
1710
|
+
allowWhiteboard Boolean @default(false)
|
|
1711
|
+
metadata Json?
|
|
1712
|
+
|
|
1713
|
+
exam Exam @relation(fields: [examId], references: [id], onDelete: Cascade)
|
|
1714
|
+
section ExamSection? @relation(fields: [sectionId], references: [id], onDelete: SetNull)
|
|
1715
|
+
responses ExamResponse[]
|
|
1716
|
+
tags ExamQuestionTag[]
|
|
1717
|
+
versions ExamQuestionVersion[]
|
|
1718
|
+
|
|
1719
|
+
@@index([examId])
|
|
1720
|
+
@@index([sectionId])
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
model ExamSession {
|
|
1724
|
+
id String @id @default(cuid())
|
|
1725
|
+
examId String
|
|
1726
|
+
userId Int
|
|
1727
|
+
status ExamSessionStatus @default(ACTIVE)
|
|
1728
|
+
progress Int @default(0)
|
|
1729
|
+
score Int @default(0)
|
|
1730
|
+
maxScore Int @default(0)
|
|
1731
|
+
grade String?
|
|
1732
|
+
timeRemainingSeconds Int?
|
|
1733
|
+
flags Json?
|
|
1734
|
+
startedAt DateTime @default(now())
|
|
1735
|
+
submittedAt DateTime?
|
|
1736
|
+
gradedAt DateTime?
|
|
1737
|
+
|
|
1738
|
+
exam Exam @relation(fields: [examId], references: [id], onDelete: Cascade)
|
|
1739
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1740
|
+
responses ExamResponse[]
|
|
1741
|
+
antiCheatFlags ExamAntiCheatFlag[]
|
|
1742
|
+
|
|
1743
|
+
@@index([examId, status])
|
|
1744
|
+
@@index([userId, startedAt])
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
model ExamResponse {
|
|
1748
|
+
id String @id @default(cuid())
|
|
1749
|
+
sessionId String
|
|
1750
|
+
questionId String
|
|
1751
|
+
answerText String?
|
|
1752
|
+
attachments Json?
|
|
1753
|
+
marksAwarded Int?
|
|
1754
|
+
isCorrect Boolean?
|
|
1755
|
+
flagged Boolean @default(false)
|
|
1756
|
+
timeSpentSeconds Int?
|
|
1757
|
+
|
|
1758
|
+
session ExamSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
|
1759
|
+
question ExamQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
1760
|
+
antiCheatFlags ExamAntiCheatFlag[]
|
|
1761
|
+
|
|
1762
|
+
@@index([sessionId])
|
|
1763
|
+
@@index([questionId])
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
model QuestionTag {
|
|
1767
|
+
id String @id @default(cuid())
|
|
1768
|
+
name String
|
|
1769
|
+
category String?
|
|
1770
|
+
description String?
|
|
1771
|
+
createdAt DateTime @default(now())
|
|
1772
|
+
|
|
1773
|
+
questions ExamQuestionTag[]
|
|
1774
|
+
|
|
1775
|
+
@@unique([name, category])
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
model ExamQuestionTag {
|
|
1779
|
+
id String @id @default(cuid())
|
|
1780
|
+
questionId String
|
|
1781
|
+
tagId String
|
|
1782
|
+
|
|
1783
|
+
question ExamQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
1784
|
+
tag QuestionTag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
|
1785
|
+
|
|
1786
|
+
@@unique([questionId, tagId])
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
model ExamQuestionVersion {
|
|
1790
|
+
id String @id @default(cuid())
|
|
1791
|
+
questionId String
|
|
1792
|
+
versionLabel String
|
|
1793
|
+
changeSummary String?
|
|
1794
|
+
snapshot Json
|
|
1795
|
+
isCurrent Boolean @default(false)
|
|
1796
|
+
createdById Int?
|
|
1797
|
+
createdAt DateTime @default(now())
|
|
1798
|
+
|
|
1799
|
+
question ExamQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
1800
|
+
createdBy User? @relation("ExamQuestionVersionAuthor", fields: [createdById], references: [id], onDelete: SetNull)
|
|
1801
|
+
|
|
1802
|
+
@@index([questionId, createdAt])
|
|
1803
|
+
@@index([createdById])
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
model ExamAntiCheatFlag {
|
|
1807
|
+
id String @id @default(cuid())
|
|
1808
|
+
sessionId String
|
|
1809
|
+
responseId String?
|
|
1810
|
+
reason String
|
|
1811
|
+
severity AntiCheatSeverity
|
|
1812
|
+
status AntiCheatStatus @default(OPEN)
|
|
1813
|
+
details String?
|
|
1814
|
+
timeline Json?
|
|
1815
|
+
metadata Json?
|
|
1816
|
+
reviewedById Int?
|
|
1817
|
+
detectedAt DateTime @default(now())
|
|
1818
|
+
reviewedAt DateTime?
|
|
1819
|
+
|
|
1820
|
+
session ExamSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
|
1821
|
+
response ExamResponse? @relation(fields: [responseId], references: [id], onDelete: SetNull)
|
|
1822
|
+
reviewedBy User? @relation("ExamAntiCheatReviewer", fields: [reviewedById], references: [id], onDelete: SetNull)
|
|
1823
|
+
|
|
1824
|
+
@@index([sessionId, status])
|
|
1825
|
+
@@index([responseId])
|
|
1826
|
+
@@index([reviewedById])
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
model CertificationRule {
|
|
1830
|
+
id String @id @default(cuid())
|
|
1831
|
+
title String
|
|
1832
|
+
description String?
|
|
1833
|
+
criteria String
|
|
1834
|
+
rewardText String?
|
|
1835
|
+
rewardXp Int @default(0)
|
|
1836
|
+
active Boolean @default(true)
|
|
1837
|
+
examId String?
|
|
1838
|
+
subjectId String?
|
|
1839
|
+
achievementId String?
|
|
1840
|
+
createdById Int?
|
|
1841
|
+
metadata Json?
|
|
1842
|
+
createdAt DateTime @default(now())
|
|
1843
|
+
updatedAt DateTime @updatedAt
|
|
1844
|
+
|
|
1845
|
+
exam Exam? @relation(fields: [examId], references: [id], onDelete: SetNull)
|
|
1846
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
1847
|
+
achievement AchievementDefinition? @relation(fields: [achievementId], references: [id], onDelete: SetNull)
|
|
1848
|
+
createdBy User? @relation("CertificationRuleCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
1849
|
+
|
|
1850
|
+
@@index([examId])
|
|
1851
|
+
@@index([subjectId])
|
|
1852
|
+
@@index([achievementId])
|
|
1853
|
+
@@index([createdById, active])
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// Data used in Hire Tutor page and tutoring dashboards.
|
|
1857
|
+
model TutorProfile {
|
|
1858
|
+
id String @id @default(cuid())
|
|
1859
|
+
userId Int @unique
|
|
1860
|
+
qualification String?
|
|
1861
|
+
bio String?
|
|
1862
|
+
yearsExperience Int?
|
|
1863
|
+
hourlyRate Float?
|
|
1864
|
+
originalHourlyRate Float?
|
|
1865
|
+
ratingAverage Float @default(0)
|
|
1866
|
+
reviewCount Int @default(0)
|
|
1867
|
+
verificationStatus TutorVerificationStatus @default(PENDING)
|
|
1868
|
+
availabilityText String?
|
|
1869
|
+
isVerified Boolean @default(false)
|
|
1870
|
+
createdAt DateTime @default(now())
|
|
1871
|
+
updatedAt DateTime @updatedAt
|
|
1872
|
+
|
|
1873
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1874
|
+
subjects TutorSubject[]
|
|
1875
|
+
availability TutorAvailability[]
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
model TutorSubject {
|
|
1879
|
+
id String @id @default(cuid())
|
|
1880
|
+
tutorProfileId String
|
|
1881
|
+
subjectId String
|
|
1882
|
+
boardId String?
|
|
1883
|
+
level CourseLevel?
|
|
1884
|
+
price Float?
|
|
1885
|
+
|
|
1886
|
+
tutorProfile TutorProfile @relation(fields: [tutorProfileId], references: [id], onDelete: Cascade)
|
|
1887
|
+
subject Subject @relation(fields: [subjectId], references: [id], onDelete: Cascade)
|
|
1888
|
+
board AcademicBoard? @relation(fields: [boardId], references: [id], onDelete: SetNull)
|
|
1889
|
+
|
|
1890
|
+
@@unique([tutorProfileId, subjectId, boardId])
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
model TutorAvailability {
|
|
1894
|
+
id String @id @default(cuid())
|
|
1895
|
+
tutorProfileId String
|
|
1896
|
+
dayOfWeek Int
|
|
1897
|
+
startTime String
|
|
1898
|
+
endTime String
|
|
1899
|
+
timezone String?
|
|
1900
|
+
available Boolean @default(true)
|
|
1901
|
+
|
|
1902
|
+
tutorProfile TutorProfile @relation(fields: [tutorProfileId], references: [id], onDelete: Cascade)
|
|
1903
|
+
|
|
1904
|
+
@@index([tutorProfileId, dayOfWeek])
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
model StudentProfile {
|
|
1908
|
+
id String @id @default(cuid())
|
|
1909
|
+
userId Int @unique
|
|
1910
|
+
grade String?
|
|
1911
|
+
targetGrade String?
|
|
1912
|
+
strengths Json?
|
|
1913
|
+
weaknesses Json?
|
|
1914
|
+
parentName String?
|
|
1915
|
+
parentEmail String?
|
|
1916
|
+
parentPhone String?
|
|
1917
|
+
attendance Int?
|
|
1918
|
+
progress Int?
|
|
1919
|
+
sessionsCompleted Int @default(0)
|
|
1920
|
+
totalSessions Int @default(0)
|
|
1921
|
+
createdAt DateTime @default(now())
|
|
1922
|
+
updatedAt DateTime @updatedAt
|
|
1923
|
+
|
|
1924
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
// Data used in the professional teacher/tutor resource dashboard.
|
|
1928
|
+
model ResourceFolder {
|
|
1929
|
+
id String @id @default(cuid())
|
|
1930
|
+
ownerId Int
|
|
1931
|
+
name String
|
|
1932
|
+
color String?
|
|
1933
|
+
description String?
|
|
1934
|
+
createdAt DateTime @default(now())
|
|
1935
|
+
updatedAt DateTime @updatedAt
|
|
1936
|
+
|
|
1937
|
+
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
1938
|
+
resources ResourceItem[]
|
|
1939
|
+
|
|
1940
|
+
@@index([ownerId, name])
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
model ResourceItem {
|
|
1944
|
+
id String @id @default(cuid())
|
|
1945
|
+
ownerId Int
|
|
1946
|
+
folderId String?
|
|
1947
|
+
courseId String?
|
|
1948
|
+
lessonId String?
|
|
1949
|
+
title String
|
|
1950
|
+
type String
|
|
1951
|
+
format String?
|
|
1952
|
+
sizeBytes Int?
|
|
1953
|
+
url String?
|
|
1954
|
+
externalUrl String?
|
|
1955
|
+
shared Boolean @default(false)
|
|
1956
|
+
starred Boolean @default(false)
|
|
1957
|
+
downloads Int @default(0)
|
|
1958
|
+
views Int @default(0)
|
|
1959
|
+
archivedAt DateTime?
|
|
1960
|
+
createdAt DateTime @default(now())
|
|
1961
|
+
lastUsedAt DateTime?
|
|
1962
|
+
updatedAt DateTime @updatedAt
|
|
1963
|
+
|
|
1964
|
+
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
1965
|
+
folder ResourceFolder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
1966
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
1967
|
+
lesson Lesson? @relation(fields: [lessonId], references: [id], onDelete: SetNull)
|
|
1968
|
+
|
|
1969
|
+
@@index([ownerId, createdAt])
|
|
1970
|
+
@@index([folderId])
|
|
1971
|
+
@@index([courseId])
|
|
1972
|
+
@@index([lessonId])
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
// Data used in professional earnings, invoices, withdrawals, and package pricing.
|
|
1976
|
+
model TutorPaymentMethod {
|
|
1977
|
+
id String @id @default(cuid())
|
|
1978
|
+
userId Int
|
|
1979
|
+
type String
|
|
1980
|
+
name String
|
|
1981
|
+
provider String?
|
|
1982
|
+
externalRef String?
|
|
1983
|
+
isDefault Boolean @default(false)
|
|
1984
|
+
status String?
|
|
1985
|
+
createdAt DateTime @default(now())
|
|
1986
|
+
updatedAt DateTime @updatedAt
|
|
1987
|
+
|
|
1988
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1989
|
+
payoutRequests PayoutRequest[]
|
|
1990
|
+
|
|
1991
|
+
@@index([userId, isDefault])
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
model PayoutRequest {
|
|
1995
|
+
id String @id @default(cuid())
|
|
1996
|
+
userId Int
|
|
1997
|
+
paymentMethodId String?
|
|
1998
|
+
amount Float
|
|
1999
|
+
currency String @default("USD")
|
|
2000
|
+
status String
|
|
2001
|
+
requestedAt DateTime @default(now())
|
|
2002
|
+
processedAt DateTime?
|
|
2003
|
+
notes String?
|
|
2004
|
+
|
|
2005
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2006
|
+
paymentMethod TutorPaymentMethod? @relation(fields: [paymentMethodId], references: [id], onDelete: SetNull)
|
|
2007
|
+
|
|
2008
|
+
@@index([userId, requestedAt])
|
|
2009
|
+
@@index([paymentMethodId])
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
model TutorPricingPackage {
|
|
2013
|
+
id String @id @default(cuid())
|
|
2014
|
+
userId Int
|
|
2015
|
+
name String
|
|
2016
|
+
price Float
|
|
2017
|
+
durationLabel String
|
|
2018
|
+
savingsLabel String?
|
|
2019
|
+
popularity Int @default(0)
|
|
2020
|
+
active Boolean @default(true)
|
|
2021
|
+
createdAt DateTime @default(now())
|
|
2022
|
+
updatedAt DateTime @updatedAt
|
|
2023
|
+
|
|
2024
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2025
|
+
|
|
2026
|
+
@@index([userId, active])
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
model TutorInvoice {
|
|
2030
|
+
id String @id @default(cuid())
|
|
2031
|
+
invoiceNumber String @unique
|
|
2032
|
+
issuerId Int
|
|
2033
|
+
studentName String
|
|
2034
|
+
studentEmail String?
|
|
2035
|
+
amount Float
|
|
2036
|
+
dueAt DateTime?
|
|
2037
|
+
paidAt DateTime?
|
|
2038
|
+
status String
|
|
2039
|
+
description String?
|
|
2040
|
+
createdAt DateTime @default(now())
|
|
2041
|
+
updatedAt DateTime @updatedAt
|
|
2042
|
+
|
|
2043
|
+
issuer User @relation("InvoiceIssuer", fields: [issuerId], references: [id], onDelete: Cascade)
|
|
2044
|
+
|
|
2045
|
+
@@index([issuerId, status])
|
|
2046
|
+
@@index([dueAt])
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
model TutorVerificationRequest {
|
|
2050
|
+
id String @id @default(cuid())
|
|
2051
|
+
userId Int
|
|
2052
|
+
status String
|
|
2053
|
+
documents Json?
|
|
2054
|
+
submittedAt DateTime @default(now())
|
|
2055
|
+
reviewedAt DateTime?
|
|
2056
|
+
reviewerId Int?
|
|
2057
|
+
notes String?
|
|
2058
|
+
|
|
2059
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2060
|
+
|
|
2061
|
+
@@index([userId, status])
|
|
2062
|
+
@@index([submittedAt])
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
model TutorBooking {
|
|
2066
|
+
id String @id @default(cuid())
|
|
2067
|
+
tutorId Int
|
|
2068
|
+
studentId Int
|
|
2069
|
+
subjectId String?
|
|
2070
|
+
requestedTopic String?
|
|
2071
|
+
message String?
|
|
2072
|
+
proposedStartAt DateTime?
|
|
2073
|
+
proposedEndAt DateTime?
|
|
2074
|
+
sessionType TutoringSessionType @default(INDIVIDUAL)
|
|
2075
|
+
format SessionFormat @default(VIRTUAL)
|
|
2076
|
+
status TutoringSessionStatus @default(REQUESTED)
|
|
2077
|
+
quotedPrice Float?
|
|
2078
|
+
createdAt DateTime @default(now())
|
|
2079
|
+
updatedAt DateTime @updatedAt
|
|
2080
|
+
tutoringSessionId String?
|
|
2081
|
+
|
|
2082
|
+
tutor User @relation("TutorBookings", fields: [tutorId], references: [id], onDelete: Cascade)
|
|
2083
|
+
student User @relation("StudentBookings", fields: [studentId], references: [id], onDelete: Cascade)
|
|
2084
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
2085
|
+
tutoringSession TutoringSession? @relation(fields: [tutoringSessionId], references: [id], onDelete: SetNull)
|
|
2086
|
+
|
|
2087
|
+
@@index([tutorId, status])
|
|
2088
|
+
@@index([studentId, status])
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
model TutoringSession {
|
|
2092
|
+
id String @id @default(cuid())
|
|
2093
|
+
tutorId Int
|
|
2094
|
+
subjectId String?
|
|
2095
|
+
boardCode String?
|
|
2096
|
+
title String
|
|
2097
|
+
topic String?
|
|
2098
|
+
sessionType TutoringSessionType @default(INDIVIDUAL)
|
|
2099
|
+
format SessionFormat @default(VIRTUAL)
|
|
2100
|
+
status TutoringSessionStatus @default(SCHEDULED)
|
|
2101
|
+
scheduledStartAt DateTime
|
|
2102
|
+
scheduledEndAt DateTime
|
|
2103
|
+
timezone String?
|
|
2104
|
+
location String?
|
|
2105
|
+
meetingUrl String?
|
|
2106
|
+
recurring Boolean @default(false)
|
|
2107
|
+
recurrenceRule String?
|
|
2108
|
+
notes String?
|
|
2109
|
+
materials Json?
|
|
2110
|
+
recordingUrl String?
|
|
2111
|
+
whiteboardState Json?
|
|
2112
|
+
maxParticipants Int?
|
|
2113
|
+
priceAmount Float?
|
|
2114
|
+
currency String? @default("USD")
|
|
2115
|
+
createdAt DateTime @default(now())
|
|
2116
|
+
updatedAt DateTime @updatedAt
|
|
2117
|
+
|
|
2118
|
+
tutor User @relation("TutorSessions", fields: [tutorId], references: [id], onDelete: Cascade)
|
|
2119
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
2120
|
+
attendees TutoringSessionAttendee[]
|
|
2121
|
+
bookings TutorBooking[]
|
|
2122
|
+
|
|
2123
|
+
@@index([tutorId, scheduledStartAt])
|
|
2124
|
+
@@index([subjectId])
|
|
2125
|
+
@@index([status])
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
model TutoringSessionAttendee {
|
|
2129
|
+
id String @id @default(cuid())
|
|
2130
|
+
tutoringSessionId String
|
|
2131
|
+
userId Int
|
|
2132
|
+
role ClassroomRole @default(STUDENT)
|
|
2133
|
+
status EnrollmentStatus @default(ACTIVE)
|
|
2134
|
+
joinedAt DateTime?
|
|
2135
|
+
leftAt DateTime?
|
|
2136
|
+
attendance Int?
|
|
2137
|
+
rating Int?
|
|
2138
|
+
feedback String?
|
|
2139
|
+
|
|
2140
|
+
tutoringSession TutoringSession @relation(fields: [tutoringSessionId], references: [id], onDelete: Cascade)
|
|
2141
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2142
|
+
|
|
2143
|
+
@@unique([tutoringSessionId, userId])
|
|
2144
|
+
@@index([userId])
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
model TutorReview {
|
|
2148
|
+
id String @id @default(cuid())
|
|
2149
|
+
tutorId Int
|
|
2150
|
+
userId Int
|
|
2151
|
+
rating Int
|
|
2152
|
+
content String?
|
|
2153
|
+
createdAt DateTime @default(now())
|
|
2154
|
+
|
|
2155
|
+
tutor User @relation("TutorReviewTarget", fields: [tutorId], references: [id], onDelete: Cascade)
|
|
2156
|
+
user User @relation("TutorReviewAuthor", fields: [userId], references: [id], onDelete: Cascade)
|
|
2157
|
+
|
|
2158
|
+
@@index([tutorId, createdAt])
|
|
2159
|
+
@@index([userId])
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
model Classroom {
|
|
2163
|
+
id String @id @default(cuid())
|
|
2164
|
+
ownerId Int
|
|
2165
|
+
courseId String?
|
|
2166
|
+
subjectId String?
|
|
2167
|
+
boardId String?
|
|
2168
|
+
name String
|
|
2169
|
+
description String?
|
|
2170
|
+
joinCode String? @unique
|
|
2171
|
+
status PublicationStatus @default(DRAFT)
|
|
2172
|
+
color String?
|
|
2173
|
+
metadata Json?
|
|
2174
|
+
createdAt DateTime @default(now())
|
|
2175
|
+
updatedAt DateTime @updatedAt
|
|
2176
|
+
|
|
2177
|
+
owner User @relation("ClassroomOwner", fields: [ownerId], references: [id], onDelete: Cascade)
|
|
2178
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
2179
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
2180
|
+
board AcademicBoard? @relation(fields: [boardId], references: [id], onDelete: SetNull)
|
|
2181
|
+
enrollments ClassroomEnrollment[]
|
|
2182
|
+
activities ClassroomActivity[]
|
|
2183
|
+
assignments Assignment[]
|
|
2184
|
+
polls ClassroomPoll[]
|
|
2185
|
+
|
|
2186
|
+
@@index([ownerId])
|
|
2187
|
+
@@index([courseId])
|
|
2188
|
+
@@index([subjectId])
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
model ClassroomEnrollment {
|
|
2192
|
+
id String @id @default(cuid())
|
|
2193
|
+
classroomId String
|
|
2194
|
+
userId Int
|
|
2195
|
+
role ClassroomRole @default(STUDENT)
|
|
2196
|
+
status EnrollmentStatus @default(ACTIVE)
|
|
2197
|
+
progress Int @default(0)
|
|
2198
|
+
attendance Int @default(0)
|
|
2199
|
+
joinedAt DateTime @default(now())
|
|
2200
|
+
|
|
2201
|
+
classroom Classroom @relation(fields: [classroomId], references: [id], onDelete: Cascade)
|
|
2202
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2203
|
+
|
|
2204
|
+
@@unique([classroomId, userId])
|
|
2205
|
+
@@index([userId, status])
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
model ClassroomActivity {
|
|
2209
|
+
id String @id @default(cuid())
|
|
2210
|
+
classroomId String
|
|
2211
|
+
type String
|
|
2212
|
+
title String
|
|
2213
|
+
description String?
|
|
2214
|
+
metadata Json?
|
|
2215
|
+
createdAt DateTime @default(now())
|
|
2216
|
+
|
|
2217
|
+
classroom Classroom @relation(fields: [classroomId], references: [id], onDelete: Cascade)
|
|
2218
|
+
|
|
2219
|
+
@@index([classroomId, createdAt])
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
model ClassroomPoll {
|
|
2223
|
+
id String @id @default(cuid())
|
|
2224
|
+
classroomId String
|
|
2225
|
+
createdById Int?
|
|
2226
|
+
question String
|
|
2227
|
+
isAnonymous Boolean @default(false)
|
|
2228
|
+
status PollStatus @default(DRAFT)
|
|
2229
|
+
startsAt DateTime?
|
|
2230
|
+
endsAt DateTime?
|
|
2231
|
+
createdAt DateTime @default(now())
|
|
2232
|
+
updatedAt DateTime @updatedAt
|
|
2233
|
+
|
|
2234
|
+
classroom Classroom @relation(fields: [classroomId], references: [id], onDelete: Cascade)
|
|
2235
|
+
createdBy User? @relation("ClassroomPollCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
2236
|
+
options ClassroomPollOption[]
|
|
2237
|
+
responses ClassroomPollResponse[]
|
|
2238
|
+
|
|
2239
|
+
@@index([classroomId, status])
|
|
2240
|
+
@@index([createdById])
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
model ClassroomPollOption {
|
|
2244
|
+
id String @id @default(cuid())
|
|
2245
|
+
pollId String
|
|
2246
|
+
text String
|
|
2247
|
+
sortOrder Int @default(0)
|
|
2248
|
+
votes Int @default(0)
|
|
2249
|
+
|
|
2250
|
+
poll ClassroomPoll @relation(fields: [pollId], references: [id], onDelete: Cascade)
|
|
2251
|
+
responses ClassroomPollResponse[]
|
|
2252
|
+
|
|
2253
|
+
@@unique([pollId, sortOrder])
|
|
2254
|
+
@@index([pollId])
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
model ClassroomPollResponse {
|
|
2258
|
+
id String @id @default(cuid())
|
|
2259
|
+
pollId String
|
|
2260
|
+
optionId String
|
|
2261
|
+
userId Int
|
|
2262
|
+
respondedAt DateTime @default(now())
|
|
2263
|
+
|
|
2264
|
+
poll ClassroomPoll @relation(fields: [pollId], references: [id], onDelete: Cascade)
|
|
2265
|
+
option ClassroomPollOption @relation(fields: [optionId], references: [id], onDelete: Cascade)
|
|
2266
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2267
|
+
|
|
2268
|
+
@@unique([pollId, userId])
|
|
2269
|
+
@@index([optionId])
|
|
2270
|
+
@@index([userId])
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
model Assignment {
|
|
2274
|
+
id String @id @default(cuid())
|
|
2275
|
+
authorId Int
|
|
2276
|
+
classroomId String?
|
|
2277
|
+
courseId String?
|
|
2278
|
+
lessonId String?
|
|
2279
|
+
title String
|
|
2280
|
+
description String?
|
|
2281
|
+
status AssignmentStatus @default(DRAFT)
|
|
2282
|
+
dueAt DateTime?
|
|
2283
|
+
maxPoints Int?
|
|
2284
|
+
attachments Json?
|
|
2285
|
+
rubric Json?
|
|
2286
|
+
metadata Json?
|
|
2287
|
+
createdAt DateTime @default(now())
|
|
2288
|
+
updatedAt DateTime @updatedAt
|
|
2289
|
+
|
|
2290
|
+
author User @relation("AssignmentAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
2291
|
+
classroom Classroom? @relation(fields: [classroomId], references: [id], onDelete: SetNull)
|
|
2292
|
+
course Course? @relation(fields: [courseId], references: [id], onDelete: SetNull)
|
|
2293
|
+
lesson Lesson? @relation(fields: [lessonId], references: [id], onDelete: SetNull)
|
|
2294
|
+
submissions AssignmentSubmission[]
|
|
2295
|
+
|
|
2296
|
+
@@index([authorId])
|
|
2297
|
+
@@index([classroomId])
|
|
2298
|
+
@@index([courseId])
|
|
2299
|
+
@@index([lessonId])
|
|
2300
|
+
@@index([status, dueAt])
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
model AssignmentSubmission {
|
|
2304
|
+
id String @id @default(cuid())
|
|
2305
|
+
assignmentId String
|
|
2306
|
+
userId Int
|
|
2307
|
+
status SubmissionStatus @default(NOT_STARTED)
|
|
2308
|
+
content String?
|
|
2309
|
+
attachments Json?
|
|
2310
|
+
score Float?
|
|
2311
|
+
feedback String?
|
|
2312
|
+
submittedAt DateTime?
|
|
2313
|
+
gradedAt DateTime?
|
|
2314
|
+
createdAt DateTime @default(now())
|
|
2315
|
+
updatedAt DateTime @updatedAt
|
|
2316
|
+
|
|
2317
|
+
assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade)
|
|
2318
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2319
|
+
|
|
2320
|
+
@@unique([assignmentId, userId])
|
|
2321
|
+
@@index([userId, status])
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
model Conversation {
|
|
2325
|
+
id String @id @default(cuid())
|
|
2326
|
+
createdById Int?
|
|
2327
|
+
type ConversationType @default(DIRECT)
|
|
2328
|
+
title String?
|
|
2329
|
+
lastMessageAt DateTime?
|
|
2330
|
+
createdAt DateTime @default(now())
|
|
2331
|
+
updatedAt DateTime @updatedAt
|
|
2332
|
+
|
|
2333
|
+
createdBy User? @relation("ConversationCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
2334
|
+
participants ConversationParticipant[]
|
|
2335
|
+
messages Message[]
|
|
2336
|
+
|
|
2337
|
+
@@index([createdById])
|
|
2338
|
+
@@index([lastMessageAt])
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
model ConversationParticipant {
|
|
2342
|
+
id String @id @default(cuid())
|
|
2343
|
+
conversationId String
|
|
2344
|
+
userId Int
|
|
2345
|
+
role ConversationParticipantRole @default(MEMBER)
|
|
2346
|
+
unreadCount Int @default(0)
|
|
2347
|
+
archivedAt DateTime?
|
|
2348
|
+
pinnedAt DateTime?
|
|
2349
|
+
joinedAt DateTime @default(now())
|
|
2350
|
+
|
|
2351
|
+
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
|
2352
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2353
|
+
|
|
2354
|
+
@@unique([conversationId, userId])
|
|
2355
|
+
@@index([userId, unreadCount])
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
model Message {
|
|
2359
|
+
id String @id @default(cuid())
|
|
2360
|
+
conversationId String
|
|
2361
|
+
senderUserId Int?
|
|
2362
|
+
senderRole MessageSenderRole @default(USER)
|
|
2363
|
+
content String
|
|
2364
|
+
metadata Json?
|
|
2365
|
+
createdAt DateTime @default(now())
|
|
2366
|
+
editedAt DateTime?
|
|
2367
|
+
readAt DateTime?
|
|
2368
|
+
|
|
2369
|
+
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
|
2370
|
+
sender User? @relation("UserMessages", fields: [senderUserId], references: [id], onDelete: SetNull)
|
|
2371
|
+
attachments MessageAttachment[]
|
|
2372
|
+
|
|
2373
|
+
@@index([conversationId, createdAt])
|
|
2374
|
+
@@index([senderUserId])
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
model MessageAttachment {
|
|
2378
|
+
id String @id @default(cuid())
|
|
2379
|
+
messageId String
|
|
2380
|
+
name String
|
|
2381
|
+
url String
|
|
2382
|
+
mimeType String?
|
|
2383
|
+
sizeBytes Int?
|
|
2384
|
+
|
|
2385
|
+
message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)
|
|
2386
|
+
|
|
2387
|
+
@@index([messageId])
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
model Announcement {
|
|
2391
|
+
id String @id @default(cuid())
|
|
2392
|
+
authorId Int
|
|
2393
|
+
title String
|
|
2394
|
+
content String
|
|
2395
|
+
recipients String?
|
|
2396
|
+
status AnnouncementStatus @default(DRAFT)
|
|
2397
|
+
scheduledFor DateTime?
|
|
2398
|
+
sentAt DateTime?
|
|
2399
|
+
createdAt DateTime @default(now())
|
|
2400
|
+
updatedAt DateTime @updatedAt
|
|
2401
|
+
|
|
2402
|
+
author User @relation("AnnouncementAuthor", fields: [authorId], references: [id], onDelete: Cascade)
|
|
2403
|
+
audience AnnouncementRecipient[]
|
|
2404
|
+
|
|
2405
|
+
@@index([authorId])
|
|
2406
|
+
@@index([status, scheduledFor])
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
model AnnouncementRecipient {
|
|
2410
|
+
id String @id @default(cuid())
|
|
2411
|
+
announcementId String
|
|
2412
|
+
userId Int
|
|
2413
|
+
deliveredAt DateTime?
|
|
2414
|
+
readAt DateTime?
|
|
2415
|
+
|
|
2416
|
+
announcement Announcement @relation(fields: [announcementId], references: [id], onDelete: Cascade)
|
|
2417
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2418
|
+
|
|
2419
|
+
@@unique([announcementId, userId])
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
model NotificationPreference {
|
|
2423
|
+
id String @id @default(cuid())
|
|
2424
|
+
userId Int @unique
|
|
2425
|
+
inAppEnabled Boolean @default(true)
|
|
2426
|
+
emailEnabled Boolean @default(true)
|
|
2427
|
+
pushEnabled Boolean @default(false)
|
|
2428
|
+
quietHoursEnabled Boolean @default(false)
|
|
2429
|
+
quietHoursStart String?
|
|
2430
|
+
quietHoursEnd String?
|
|
2431
|
+
digestMode NotificationDigestMode @default(NONE)
|
|
2432
|
+
notifyGameInvites Boolean @default(true)
|
|
2433
|
+
notifyQuizUpdates Boolean @default(true)
|
|
2434
|
+
notifyAchievements Boolean @default(true)
|
|
2435
|
+
notifyFollowers Boolean @default(true)
|
|
2436
|
+
notifyComments Boolean @default(true)
|
|
2437
|
+
notifyMarketing Boolean @default(false)
|
|
2438
|
+
emailNewBooking Boolean @default(true)
|
|
2439
|
+
emailCancellation Boolean @default(true)
|
|
2440
|
+
emailMessages Boolean @default(true)
|
|
2441
|
+
emailWeeklyReport Boolean @default(true)
|
|
2442
|
+
pushNewBooking Boolean @default(true)
|
|
2443
|
+
pushMessages Boolean @default(true)
|
|
2444
|
+
pushReminders Boolean @default(true)
|
|
2445
|
+
smsReminders Boolean @default(false)
|
|
2446
|
+
allowDirectMessages Boolean @default(true)
|
|
2447
|
+
updatedAt DateTime @updatedAt
|
|
2448
|
+
|
|
2449
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
model Notification {
|
|
2453
|
+
id String @id @default(cuid())
|
|
2454
|
+
userId Int
|
|
2455
|
+
type NotificationType @default(GENERAL)
|
|
2456
|
+
channel NotificationChannel @default(IN_APP)
|
|
2457
|
+
title String?
|
|
2458
|
+
content String
|
|
2459
|
+
actionUrl String?
|
|
2460
|
+
isRead Boolean @default(false)
|
|
2461
|
+
readAt DateTime?
|
|
2462
|
+
metadata Json?
|
|
2463
|
+
createdAt DateTime @default(now())
|
|
2464
|
+
|
|
2465
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2466
|
+
|
|
2467
|
+
@@index([userId, isRead, createdAt])
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
model SupportTicket {
|
|
2471
|
+
id String @id @default(cuid())
|
|
2472
|
+
requesterId Int
|
|
2473
|
+
assigneeId Int?
|
|
2474
|
+
conversationId String? @unique
|
|
2475
|
+
subject String
|
|
2476
|
+
description String
|
|
2477
|
+
category String
|
|
2478
|
+
status SupportStatus @default(OPEN)
|
|
2479
|
+
priority SupportPriority @default(MEDIUM)
|
|
2480
|
+
metadata Json?
|
|
2481
|
+
createdAt DateTime @default(now())
|
|
2482
|
+
updatedAt DateTime @updatedAt
|
|
2483
|
+
resolvedAt DateTime?
|
|
2484
|
+
|
|
2485
|
+
requester User @relation("SupportTicketRequester", fields: [requesterId], references: [id], onDelete: Cascade)
|
|
2486
|
+
assignee User? @relation("SupportTicketAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
|
2487
|
+
conversation SupportConversation? @relation(fields: [conversationId], references: [id], onDelete: SetNull)
|
|
2488
|
+
|
|
2489
|
+
@@index([requesterId])
|
|
2490
|
+
@@index([assigneeId])
|
|
2491
|
+
@@index([status, priority])
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
model SupportConversation {
|
|
2495
|
+
id String @id @default(cuid())
|
|
2496
|
+
userId Int
|
|
2497
|
+
agentId Int?
|
|
2498
|
+
subject String?
|
|
2499
|
+
lastMessage String?
|
|
2500
|
+
lastMessageAt DateTime?
|
|
2501
|
+
unreadCount Int @default(0)
|
|
2502
|
+
status SupportStatus @default(OPEN)
|
|
2503
|
+
createdAt DateTime @default(now())
|
|
2504
|
+
updatedAt DateTime @updatedAt
|
|
2505
|
+
|
|
2506
|
+
user User @relation("SupportConversationRequester", fields: [userId], references: [id], onDelete: Cascade)
|
|
2507
|
+
agent User? @relation("SupportConversationAgent", fields: [agentId], references: [id], onDelete: SetNull)
|
|
2508
|
+
ticket SupportTicket?
|
|
2509
|
+
messages SupportMessage[]
|
|
2510
|
+
|
|
2511
|
+
@@index([userId, status])
|
|
2512
|
+
@@index([agentId])
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
model SupportMessage {
|
|
2516
|
+
id String @id @default(cuid())
|
|
2517
|
+
conversationId String
|
|
2518
|
+
authorId Int?
|
|
2519
|
+
senderName String
|
|
2520
|
+
senderRole MessageSenderRole @default(USER)
|
|
2521
|
+
senderAvatar String?
|
|
2522
|
+
text String
|
|
2523
|
+
isRead Boolean @default(false)
|
|
2524
|
+
createdAt DateTime @default(now())
|
|
2525
|
+
|
|
2526
|
+
conversation SupportConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
|
2527
|
+
author User? @relation("SupportMessageAuthor", fields: [authorId], references: [id], onDelete: SetNull)
|
|
2528
|
+
attachments SupportAttachment[]
|
|
2529
|
+
|
|
2530
|
+
@@index([conversationId, createdAt])
|
|
2531
|
+
@@index([authorId])
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
model SupportAttachment {
|
|
2535
|
+
id String @id @default(cuid())
|
|
2536
|
+
messageId String
|
|
2537
|
+
name String
|
|
2538
|
+
url String
|
|
2539
|
+
type String
|
|
2540
|
+
size Int
|
|
2541
|
+
|
|
2542
|
+
message SupportMessage @relation(fields: [messageId], references: [id], onDelete: Cascade)
|
|
2543
|
+
|
|
2544
|
+
@@index([messageId])
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
model Community {
|
|
2548
|
+
id String @id @default(cuid())
|
|
2549
|
+
ownerId Int
|
|
2550
|
+
subjectId String?
|
|
2551
|
+
name String
|
|
2552
|
+
slug String? @unique
|
|
2553
|
+
description String?
|
|
2554
|
+
visibility CommunityVisibility @default(PUBLIC)
|
|
2555
|
+
createdAt DateTime @default(now())
|
|
2556
|
+
updatedAt DateTime @updatedAt
|
|
2557
|
+
|
|
2558
|
+
owner User @relation("CommunityOwner", fields: [ownerId], references: [id], onDelete: Cascade)
|
|
2559
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
2560
|
+
memberships CommunityMembership[]
|
|
2561
|
+
posts CommunityPost[]
|
|
2562
|
+
events CommunityEvent[]
|
|
2563
|
+
resources CommunityResource[]
|
|
2564
|
+
|
|
2565
|
+
@@index([ownerId])
|
|
2566
|
+
@@index([subjectId])
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
model CommunityMembership {
|
|
2570
|
+
id String @id @default(cuid())
|
|
2571
|
+
communityId String
|
|
2572
|
+
userId Int
|
|
2573
|
+
joinedAt DateTime @default(now())
|
|
2574
|
+
|
|
2575
|
+
community Community @relation(fields: [communityId], references: [id], onDelete: Cascade)
|
|
2576
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2577
|
+
|
|
2578
|
+
@@unique([communityId, userId])
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
model CommunityPost {
|
|
2582
|
+
id String @id @default(cuid())
|
|
2583
|
+
communityId String
|
|
2584
|
+
authorId Int
|
|
2585
|
+
content String
|
|
2586
|
+
images Json?
|
|
2587
|
+
codeSnippet String?
|
|
2588
|
+
tags Json?
|
|
2589
|
+
likes Int @default(0)
|
|
2590
|
+
isPinned Boolean @default(false)
|
|
2591
|
+
createdAt DateTime @default(now())
|
|
2592
|
+
updatedAt DateTime @updatedAt
|
|
2593
|
+
|
|
2594
|
+
community Community @relation(fields: [communityId], references: [id], onDelete: Cascade)
|
|
2595
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
2596
|
+
replies CommunityReply[]
|
|
2597
|
+
|
|
2598
|
+
@@index([communityId, createdAt])
|
|
2599
|
+
@@index([authorId])
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
model CommunityReply {
|
|
2603
|
+
id String @id @default(cuid())
|
|
2604
|
+
postId String
|
|
2605
|
+
authorId Int
|
|
2606
|
+
content String
|
|
2607
|
+
likes Int @default(0)
|
|
2608
|
+
createdAt DateTime @default(now())
|
|
2609
|
+
|
|
2610
|
+
post CommunityPost @relation(fields: [postId], references: [id], onDelete: Cascade)
|
|
2611
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
2612
|
+
|
|
2613
|
+
@@index([postId, createdAt])
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
model CommunityEvent {
|
|
2617
|
+
id String @id @default(cuid())
|
|
2618
|
+
communityId String
|
|
2619
|
+
hostId Int?
|
|
2620
|
+
title String
|
|
2621
|
+
description String?
|
|
2622
|
+
startsAt DateTime
|
|
2623
|
+
endsAt DateTime?
|
|
2624
|
+
location String?
|
|
2625
|
+
metadata Json?
|
|
2626
|
+
createdAt DateTime @default(now())
|
|
2627
|
+
|
|
2628
|
+
community Community @relation(fields: [communityId], references: [id], onDelete: Cascade)
|
|
2629
|
+
host User? @relation("CommunityEventHost", fields: [hostId], references: [id], onDelete: SetNull)
|
|
2630
|
+
|
|
2631
|
+
@@index([communityId, startsAt])
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
model CommunityResource {
|
|
2635
|
+
id String @id @default(cuid())
|
|
2636
|
+
communityId String
|
|
2637
|
+
title String
|
|
2638
|
+
description String?
|
|
2639
|
+
type CommunityResourceType
|
|
2640
|
+
url String?
|
|
2641
|
+
metadata Json?
|
|
2642
|
+
createdAt DateTime @default(now())
|
|
2643
|
+
|
|
2644
|
+
community Community @relation(fields: [communityId], references: [id], onDelete: Cascade)
|
|
2645
|
+
|
|
2646
|
+
@@index([communityId, type])
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
model UserActivityEvent {
|
|
2650
|
+
id String @id @default(cuid())
|
|
2651
|
+
userId Int
|
|
2652
|
+
subjectId String?
|
|
2653
|
+
type UserEventType
|
|
2654
|
+
title String
|
|
2655
|
+
subjectName String?
|
|
2656
|
+
boardCode String?
|
|
2657
|
+
topic String?
|
|
2658
|
+
occurredAt DateTime
|
|
2659
|
+
durationMinutes Int @default(0)
|
|
2660
|
+
status UserEventStatus @default(COMPLETED)
|
|
2661
|
+
placement PlacementTier @default(PARTICIPATED)
|
|
2662
|
+
rank Int?
|
|
2663
|
+
totalParticipants Int?
|
|
2664
|
+
score Int?
|
|
2665
|
+
maxScore Int?
|
|
2666
|
+
accuracy Float?
|
|
2667
|
+
correctAnswers Int?
|
|
2668
|
+
totalQuestions Int?
|
|
2669
|
+
xpEarned Int @default(0)
|
|
2670
|
+
streakBonus Int?
|
|
2671
|
+
achievements Json?
|
|
2672
|
+
hostName String?
|
|
2673
|
+
hostAvatar String?
|
|
2674
|
+
gameCode String?
|
|
2675
|
+
avgResponseTime Float?
|
|
2676
|
+
fastestAnswer Float?
|
|
2677
|
+
longestStreak Int?
|
|
2678
|
+
improvement Float?
|
|
2679
|
+
difficulty String?
|
|
2680
|
+
badges Json?
|
|
2681
|
+
metadata Json?
|
|
2682
|
+
|
|
2683
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2684
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
2685
|
+
|
|
2686
|
+
@@index([userId, occurredAt])
|
|
2687
|
+
@@index([subjectId])
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
model Feedback {
|
|
2691
|
+
id String @id @default(cuid())
|
|
2692
|
+
userId Int?
|
|
2693
|
+
type FeedbackType
|
|
2694
|
+
email String?
|
|
2695
|
+
page String?
|
|
2696
|
+
message String
|
|
2697
|
+
rating Int?
|
|
2698
|
+
status FeedbackStatus @default(NEW)
|
|
2699
|
+
priority SupportPriority @default(MEDIUM)
|
|
2700
|
+
createdAt DateTime @default(now())
|
|
2701
|
+
updatedAt DateTime @updatedAt
|
|
2702
|
+
|
|
2703
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
2704
|
+
|
|
2705
|
+
@@index([userId])
|
|
2706
|
+
@@index([type, status])
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
// Data used in admin user-management, moderation, security, monitoring, and data tools.
|
|
2710
|
+
model FraudAlert {
|
|
2711
|
+
id String @id @default(cuid())
|
|
2712
|
+
userId Int?
|
|
2713
|
+
type String
|
|
2714
|
+
riskScore Int
|
|
2715
|
+
details String
|
|
2716
|
+
status String
|
|
2717
|
+
detectedAt DateTime @default(now())
|
|
2718
|
+
resolvedAt DateTime?
|
|
2719
|
+
resolutionNotes String?
|
|
2720
|
+
|
|
2721
|
+
@@index([userId, status])
|
|
2722
|
+
@@index([riskScore, detectedAt])
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
model BehavioralRule {
|
|
2726
|
+
id String @id @default(cuid())
|
|
2727
|
+
name String
|
|
2728
|
+
description String
|
|
2729
|
+
severity String
|
|
2730
|
+
autoAction String
|
|
2731
|
+
enabled Boolean @default(true)
|
|
2732
|
+
createdAt DateTime @default(now())
|
|
2733
|
+
updatedAt DateTime @updatedAt
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
model ModerationCase {
|
|
2737
|
+
id String @id @default(cuid())
|
|
2738
|
+
contentType String
|
|
2739
|
+
contentId String?
|
|
2740
|
+
title String
|
|
2741
|
+
authorName String?
|
|
2742
|
+
authorUserId Int?
|
|
2743
|
+
reason String
|
|
2744
|
+
reportCount Int @default(0)
|
|
2745
|
+
status String
|
|
2746
|
+
priority String
|
|
2747
|
+
preview String?
|
|
2748
|
+
aiAction String?
|
|
2749
|
+
aiConfidence Int?
|
|
2750
|
+
aiReason String?
|
|
2751
|
+
openedAt DateTime @default(now())
|
|
2752
|
+
reviewedAt DateTime?
|
|
2753
|
+
|
|
2754
|
+
actions ModerationAction[]
|
|
2755
|
+
|
|
2756
|
+
@@index([status, priority])
|
|
2757
|
+
@@index([authorUserId])
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
model ModerationAction {
|
|
2761
|
+
id String @id @default(cuid())
|
|
2762
|
+
moderationCaseId String
|
|
2763
|
+
action String
|
|
2764
|
+
moderatorName String?
|
|
2765
|
+
moderatorId Int?
|
|
2766
|
+
reason String?
|
|
2767
|
+
aiAssisted Boolean @default(false)
|
|
2768
|
+
createdAt DateTime @default(now())
|
|
2769
|
+
|
|
2770
|
+
moderationCase ModerationCase @relation(fields: [moderationCaseId], references: [id], onDelete: Cascade)
|
|
2771
|
+
|
|
2772
|
+
@@index([moderationCaseId, createdAt])
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
model ModerationRule {
|
|
2776
|
+
id String @id @default(cuid())
|
|
2777
|
+
name String
|
|
2778
|
+
category String?
|
|
2779
|
+
status String
|
|
2780
|
+
sensitivity Int?
|
|
2781
|
+
falsePositiveRate Float?
|
|
2782
|
+
matches Int @default(0)
|
|
2783
|
+
lastTriggeredAt DateTime?
|
|
2784
|
+
createdAt DateTime @default(now())
|
|
2785
|
+
updatedAt DateTime @updatedAt
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
model IpBan {
|
|
2789
|
+
id String @id @default(cuid())
|
|
2790
|
+
ipAddress String @unique
|
|
2791
|
+
reason String
|
|
2792
|
+
bannedBy String?
|
|
2793
|
+
attempts Int @default(0)
|
|
2794
|
+
bannedAt DateTime @default(now())
|
|
2795
|
+
expiresAt DateTime?
|
|
2796
|
+
isPermanent Boolean @default(false)
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
model SecurityScan {
|
|
2800
|
+
id String @id @default(cuid())
|
|
2801
|
+
scanType String
|
|
2802
|
+
status String
|
|
2803
|
+
issuesFound Int @default(0)
|
|
2804
|
+
startedAt DateTime?
|
|
2805
|
+
completedAt DateTime?
|
|
2806
|
+
durationSeconds Int?
|
|
2807
|
+
metadata Json?
|
|
2808
|
+
createdAt DateTime @default(now())
|
|
2809
|
+
|
|
2810
|
+
@@index([status, createdAt])
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
model SecurityTwoFactorMethod {
|
|
2814
|
+
id String @id @default(cuid())
|
|
2815
|
+
userId Int
|
|
2816
|
+
method String
|
|
2817
|
+
enabledAt DateTime @default(now())
|
|
2818
|
+
lastUsedAt DateTime?
|
|
2819
|
+
active Boolean @default(true)
|
|
2820
|
+
|
|
2821
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
2822
|
+
|
|
2823
|
+
@@index([userId, active])
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
model ApiEndpointStat {
|
|
2827
|
+
id String @id @default(cuid())
|
|
2828
|
+
endpoint String
|
|
2829
|
+
method String
|
|
2830
|
+
status String
|
|
2831
|
+
latencyMs Int?
|
|
2832
|
+
requests Int @default(0)
|
|
2833
|
+
errors Int @default(0)
|
|
2834
|
+
capturedAt DateTime @default(now())
|
|
2835
|
+
|
|
2836
|
+
@@index([endpoint, method, capturedAt])
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
model ApiBillingTier {
|
|
2840
|
+
id String @id @default(cuid())
|
|
2841
|
+
name String @unique
|
|
2842
|
+
monthlyCallLimit Int?
|
|
2843
|
+
requestsPerMinute Int?
|
|
2844
|
+
dailyRequestLimit Int?
|
|
2845
|
+
burstLimit Int?
|
|
2846
|
+
price Float @default(0)
|
|
2847
|
+
active Boolean @default(true)
|
|
2848
|
+
isDefault Boolean @default(false)
|
|
2849
|
+
createdAt DateTime @default(now())
|
|
2850
|
+
updatedAt DateTime @updatedAt
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
model ApplicationErrorLog {
|
|
2854
|
+
id String @id @default(cuid())
|
|
2855
|
+
errorCode String?
|
|
2856
|
+
errorType String
|
|
2857
|
+
message String
|
|
2858
|
+
filePath String?
|
|
2859
|
+
stack String?
|
|
2860
|
+
status String
|
|
2861
|
+
count Int @default(1)
|
|
2862
|
+
firstSeenAt DateTime @default(now())
|
|
2863
|
+
lastSeenAt DateTime?
|
|
2864
|
+
|
|
2865
|
+
@@index([status, lastSeenAt])
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
model SystemLogEntry {
|
|
2869
|
+
id String @id @default(cuid())
|
|
2870
|
+
level String
|
|
2871
|
+
message String
|
|
2872
|
+
source String?
|
|
2873
|
+
endpoint String?
|
|
2874
|
+
count Int?
|
|
2875
|
+
createdAt DateTime @default(now())
|
|
2876
|
+
|
|
2877
|
+
@@index([level, createdAt])
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
model SystemIncident {
|
|
2881
|
+
id String @id @default(cuid())
|
|
2882
|
+
title String
|
|
2883
|
+
status String
|
|
2884
|
+
severity String
|
|
2885
|
+
startTime DateTime
|
|
2886
|
+
resolvedTime DateTime?
|
|
2887
|
+
affectedServices Json?
|
|
2888
|
+
assignee String?
|
|
2889
|
+
createdAt DateTime @default(now())
|
|
2890
|
+
updatedAt DateTime @updatedAt
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
model SystemAlertRule {
|
|
2894
|
+
id String @id @default(cuid())
|
|
2895
|
+
name String
|
|
2896
|
+
channel String
|
|
2897
|
+
threshold String
|
|
2898
|
+
recipients String?
|
|
2899
|
+
escalation String?
|
|
2900
|
+
enabled Boolean @default(true)
|
|
2901
|
+
createdAt DateTime @default(now())
|
|
2902
|
+
updatedAt DateTime @updatedAt
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
model IncidentPlaybook {
|
|
2906
|
+
id String @id @default(cuid())
|
|
2907
|
+
name String
|
|
2908
|
+
description String?
|
|
2909
|
+
stepsCount Int @default(0)
|
|
2910
|
+
severity String?
|
|
2911
|
+
lastUsedAt DateTime?
|
|
2912
|
+
createdAt DateTime @default(now())
|
|
2913
|
+
updatedAt DateTime @updatedAt
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
model DeploymentRelease {
|
|
2917
|
+
id String @id @default(cuid())
|
|
2918
|
+
version String @unique
|
|
2919
|
+
environment String?
|
|
2920
|
+
deployedAt DateTime
|
|
2921
|
+
status String
|
|
2922
|
+
healthy Boolean @default(true)
|
|
2923
|
+
notes String?
|
|
2924
|
+
createdAt DateTime @default(now())
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
model RollbackEvent {
|
|
2928
|
+
id String @id @default(cuid())
|
|
2929
|
+
deploymentVersion String
|
|
2930
|
+
rolledBackTo String
|
|
2931
|
+
reason String
|
|
2932
|
+
initiatedBy String?
|
|
2933
|
+
status String
|
|
2934
|
+
durationSeconds Int?
|
|
2935
|
+
createdAt DateTime @default(now())
|
|
2936
|
+
|
|
2937
|
+
@@index([deploymentVersion, createdAt])
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
model GdprRequest {
|
|
2941
|
+
id String @id @default(cuid())
|
|
2942
|
+
userId Int?
|
|
2943
|
+
email String
|
|
2944
|
+
requestType String
|
|
2945
|
+
status String
|
|
2946
|
+
requestedAt DateTime @default(now())
|
|
2947
|
+
completedAt DateTime?
|
|
2948
|
+
|
|
2949
|
+
@@index([userId, status])
|
|
2950
|
+
@@index([email])
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
model DataRetentionPolicy {
|
|
2954
|
+
id String @id @default(cuid())
|
|
2955
|
+
name String
|
|
2956
|
+
retention String
|
|
2957
|
+
description String?
|
|
2958
|
+
status String
|
|
2959
|
+
lastRunAt DateTime?
|
|
2960
|
+
nextRunAt DateTime?
|
|
2961
|
+
createdAt DateTime @default(now())
|
|
2962
|
+
updatedAt DateTime @updatedAt
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
model DataExportConfig {
|
|
2966
|
+
id String @id @default(cuid())
|
|
2967
|
+
name String
|
|
2968
|
+
format String
|
|
2969
|
+
tables Json
|
|
2970
|
+
schedule String?
|
|
2971
|
+
status String
|
|
2972
|
+
lastExportAt DateTime?
|
|
2973
|
+
createdAt DateTime @default(now())
|
|
2974
|
+
updatedAt DateTime @updatedAt
|
|
2975
|
+
|
|
2976
|
+
runs DataExportRun[]
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
model DataExportRun {
|
|
2980
|
+
id String @id @default(cuid())
|
|
2981
|
+
configId String?
|
|
2982
|
+
exportName String
|
|
2983
|
+
format String
|
|
2984
|
+
rowCount Int @default(0)
|
|
2985
|
+
sizeBytes Int?
|
|
2986
|
+
exportedBy String?
|
|
2987
|
+
status String
|
|
2988
|
+
executedAt DateTime @default(now())
|
|
2989
|
+
|
|
2990
|
+
config DataExportConfig? @relation(fields: [configId], references: [id], onDelete: SetNull)
|
|
2991
|
+
|
|
2992
|
+
@@index([configId, executedAt])
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
model DataTransformation {
|
|
2996
|
+
id String @id @default(cuid())
|
|
2997
|
+
name String
|
|
2998
|
+
description String?
|
|
2999
|
+
enabled Boolean @default(true)
|
|
3000
|
+
createdAt DateTime @default(now())
|
|
3001
|
+
updatedAt DateTime @updatedAt
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
model PolicySimulation {
|
|
3005
|
+
id String @id @default(cuid())
|
|
3006
|
+
policyName String
|
|
3007
|
+
recordsAffected Int @default(0)
|
|
3008
|
+
dataSizeBytes Int?
|
|
3009
|
+
estimatedDurationSeconds Int?
|
|
3010
|
+
createdAt DateTime @default(now())
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
model NotificationTemplate {
|
|
3014
|
+
id String @id @default(cuid())
|
|
3015
|
+
name String
|
|
3016
|
+
channelType String
|
|
3017
|
+
category String
|
|
3018
|
+
subject String?
|
|
3019
|
+
body String?
|
|
3020
|
+
uses Int @default(0)
|
|
3021
|
+
active Boolean @default(true)
|
|
3022
|
+
createdAt DateTime @default(now())
|
|
3023
|
+
updatedAt DateTime @updatedAt
|
|
3024
|
+
}
|
|
3025
|
+
|
|
3026
|
+
model NotificationCampaign {
|
|
3027
|
+
id String @id @default(cuid())
|
|
3028
|
+
campaignType String
|
|
3029
|
+
title String
|
|
3030
|
+
message String
|
|
3031
|
+
status String
|
|
3032
|
+
recipientsCount Int @default(0)
|
|
3033
|
+
readCount Int @default(0)
|
|
3034
|
+
channels Json?
|
|
3035
|
+
scheduledAt DateTime?
|
|
3036
|
+
sentAt DateTime?
|
|
3037
|
+
createdAt DateTime @default(now())
|
|
3038
|
+
updatedAt DateTime @updatedAt
|
|
3039
|
+
}
|
|
3040
|
+
|
|
3041
|
+
model ApiKeyRotationEvent {
|
|
3042
|
+
id String @id @default(cuid())
|
|
3043
|
+
apiKeyId String?
|
|
3044
|
+
keyName String
|
|
3045
|
+
previousKey String?
|
|
3046
|
+
rotatedBy String?
|
|
3047
|
+
reason String?
|
|
3048
|
+
rotatedAt DateTime @default(now())
|
|
3049
|
+
|
|
3050
|
+
@@index([apiKeyId, rotatedAt])
|
|
3051
|
+
}
|
|
3052
|
+
|
|
3053
|
+
model IntegrationHealthLog {
|
|
3054
|
+
id String @id @default(cuid())
|
|
3055
|
+
integrationId String?
|
|
3056
|
+
name String
|
|
3057
|
+
status String
|
|
3058
|
+
details String?
|
|
3059
|
+
resolved Boolean @default(false)
|
|
3060
|
+
recordedAt DateTime @default(now())
|
|
3061
|
+
|
|
3062
|
+
@@index([integrationId, recordedAt])
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
model SandboxEnvironment {
|
|
3066
|
+
id String @id @default(cuid())
|
|
3067
|
+
name String
|
|
3068
|
+
status SandboxStatus @default(STOPPED)
|
|
3069
|
+
baseEnvironment DeploymentEnvironment?
|
|
3070
|
+
url String?
|
|
3071
|
+
ownerName String?
|
|
3072
|
+
createdById Int?
|
|
3073
|
+
seeded Boolean @default(false)
|
|
3074
|
+
dataSizeBytes Int?
|
|
3075
|
+
autoDestroyAt DateTime?
|
|
3076
|
+
lastAccessAt DateTime?
|
|
3077
|
+
metadata Json?
|
|
3078
|
+
createdAt DateTime @default(now())
|
|
3079
|
+
updatedAt DateTime @updatedAt
|
|
3080
|
+
|
|
3081
|
+
createdBy User? @relation("SandboxCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
3082
|
+
promotions SandboxPromotion[]
|
|
3083
|
+
seedRuns DataSeedRun[]
|
|
3084
|
+
|
|
3085
|
+
@@index([status, createdAt])
|
|
3086
|
+
@@index([createdById])
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
model SandboxPromotion {
|
|
3090
|
+
id String @id @default(cuid())
|
|
3091
|
+
sandboxId String
|
|
3092
|
+
promotedTo DeploymentEnvironment
|
|
3093
|
+
promotedById Int?
|
|
3094
|
+
promotedByName String?
|
|
3095
|
+
status SandboxPromotionStatus @default(PENDING)
|
|
3096
|
+
filesChanged Int @default(0)
|
|
3097
|
+
notes String?
|
|
3098
|
+
promotedAt DateTime @default(now())
|
|
3099
|
+
|
|
3100
|
+
sandbox SandboxEnvironment @relation(fields: [sandboxId], references: [id], onDelete: Cascade)
|
|
3101
|
+
promotedBy User? @relation("SandboxPromotionActor", fields: [promotedById], references: [id], onDelete: SetNull)
|
|
3102
|
+
|
|
3103
|
+
@@index([sandboxId, promotedAt])
|
|
3104
|
+
@@index([promotedById])
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
model DataSeed {
|
|
3108
|
+
id String @id @default(cuid())
|
|
3109
|
+
name String
|
|
3110
|
+
description String?
|
|
3111
|
+
category String?
|
|
3112
|
+
sizeBytes Int?
|
|
3113
|
+
recordCount Int @default(0)
|
|
3114
|
+
metadata Json?
|
|
3115
|
+
lastRunAt DateTime?
|
|
3116
|
+
active Boolean @default(true)
|
|
3117
|
+
createdAt DateTime @default(now())
|
|
3118
|
+
updatedAt DateTime @updatedAt
|
|
3119
|
+
|
|
3120
|
+
runs DataSeedRun[]
|
|
3121
|
+
|
|
3122
|
+
@@index([category, active])
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
model DataSeedRun {
|
|
3126
|
+
id String @id @default(cuid())
|
|
3127
|
+
seedId String
|
|
3128
|
+
sandboxId String?
|
|
3129
|
+
triggeredById Int?
|
|
3130
|
+
status String
|
|
3131
|
+
recordsCreated Int @default(0)
|
|
3132
|
+
executedAt DateTime @default(now())
|
|
3133
|
+
completedAt DateTime?
|
|
3134
|
+
|
|
3135
|
+
seed DataSeed @relation(fields: [seedId], references: [id], onDelete: Cascade)
|
|
3136
|
+
sandbox SandboxEnvironment? @relation(fields: [sandboxId], references: [id], onDelete: SetNull)
|
|
3137
|
+
triggeredBy User? @relation("DataSeedRunActor", fields: [triggeredById], references: [id], onDelete: SetNull)
|
|
3138
|
+
|
|
3139
|
+
@@index([seedId, executedAt])
|
|
3140
|
+
@@index([sandboxId])
|
|
3141
|
+
@@index([triggeredById])
|
|
3142
|
+
}
|
|
3143
|
+
|
|
3144
|
+
model FeatureFlag {
|
|
3145
|
+
id String @id @default(cuid())
|
|
3146
|
+
key String @unique
|
|
3147
|
+
name String
|
|
3148
|
+
description String?
|
|
3149
|
+
status FeatureFlagStatus @default(DISABLED)
|
|
3150
|
+
environment DeploymentEnvironment @default(DEVELOPMENT)
|
|
3151
|
+
rollout Int @default(0)
|
|
3152
|
+
targeting String?
|
|
3153
|
+
lastModifiedBy String?
|
|
3154
|
+
createdAt DateTime @default(now())
|
|
3155
|
+
updatedAt DateTime @updatedAt
|
|
3156
|
+
|
|
3157
|
+
rules FeatureFlagRule[]
|
|
3158
|
+
experiments FeatureExperiment[]
|
|
3159
|
+
|
|
3160
|
+
@@index([environment, status])
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
model FeatureFlagRule {
|
|
3164
|
+
id String @id @default(cuid())
|
|
3165
|
+
featureFlagId String
|
|
3166
|
+
name String
|
|
3167
|
+
condition String
|
|
3168
|
+
action String
|
|
3169
|
+
enabled Boolean @default(true)
|
|
3170
|
+
metadata Json?
|
|
3171
|
+
createdAt DateTime @default(now())
|
|
3172
|
+
|
|
3173
|
+
featureFlag FeatureFlag @relation(fields: [featureFlagId], references: [id], onDelete: Cascade)
|
|
3174
|
+
|
|
3175
|
+
@@index([featureFlagId, enabled])
|
|
3176
|
+
}
|
|
3177
|
+
|
|
3178
|
+
model FeatureExperiment {
|
|
3179
|
+
id String @id @default(cuid())
|
|
3180
|
+
featureFlagId String?
|
|
3181
|
+
name String
|
|
3182
|
+
hypothesis String?
|
|
3183
|
+
status ExperimentStatus @default(DRAFT)
|
|
3184
|
+
startDate DateTime?
|
|
3185
|
+
endDate DateTime?
|
|
3186
|
+
significance Float?
|
|
3187
|
+
winner String?
|
|
3188
|
+
variants Json?
|
|
3189
|
+
metadata Json?
|
|
3190
|
+
createdAt DateTime @default(now())
|
|
3191
|
+
|
|
3192
|
+
featureFlag FeatureFlag? @relation(fields: [featureFlagId], references: [id], onDelete: SetNull)
|
|
3193
|
+
|
|
3194
|
+
@@index([featureFlagId])
|
|
3195
|
+
@@index([status, startDate])
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
model SpacedRepetitionConfig {
|
|
3199
|
+
id String @id @default("default")
|
|
3200
|
+
masteryThreshold Int @default(90)
|
|
3201
|
+
initialReviewHours Int @default(24)
|
|
3202
|
+
difficultyWeighting Float @default(1.5)
|
|
3203
|
+
dailyReviewLimit Int @default(50)
|
|
3204
|
+
adaptiveDifficulty Boolean @default(true)
|
|
3205
|
+
updatedAt DateTime @updatedAt
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
model RewardRule {
|
|
3209
|
+
id String @id @default(cuid())
|
|
3210
|
+
scope RewardScope
|
|
3211
|
+
name String
|
|
3212
|
+
description String?
|
|
3213
|
+
status RewardStatus @default(DRAFT)
|
|
3214
|
+
rewardType String?
|
|
3215
|
+
conditions Json?
|
|
3216
|
+
rewards Json?
|
|
3217
|
+
startsAt DateTime?
|
|
3218
|
+
endsAt DateTime?
|
|
3219
|
+
createdById Int?
|
|
3220
|
+
createdAt DateTime @default(now())
|
|
3221
|
+
updatedAt DateTime @updatedAt
|
|
3222
|
+
|
|
3223
|
+
createdBy User? @relation("RewardRuleCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
3224
|
+
|
|
3225
|
+
@@index([scope, status])
|
|
3226
|
+
@@index([createdById])
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
model Role {
|
|
3230
|
+
id String @id @default(cuid())
|
|
3231
|
+
name String @unique
|
|
3232
|
+
description String?
|
|
3233
|
+
color String?
|
|
3234
|
+
createdAt DateTime @default(now())
|
|
3235
|
+
updatedAt DateTime @updatedAt
|
|
3236
|
+
|
|
3237
|
+
permissions RolePermission[]
|
|
3238
|
+
assignments UserRoleAssignment[]
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
model Permission {
|
|
3242
|
+
id String @id @default(cuid())
|
|
3243
|
+
key String @unique
|
|
3244
|
+
groupName String
|
|
3245
|
+
name String
|
|
3246
|
+
description String?
|
|
3247
|
+
|
|
3248
|
+
roles RolePermission[]
|
|
3249
|
+
|
|
3250
|
+
@@index([groupName])
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
model RolePermission {
|
|
3254
|
+
id String @id @default(cuid())
|
|
3255
|
+
roleId String
|
|
3256
|
+
permissionId String
|
|
3257
|
+
|
|
3258
|
+
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
3259
|
+
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
3260
|
+
|
|
3261
|
+
@@unique([roleId, permissionId])
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
model UserRoleAssignment {
|
|
3265
|
+
id String @id @default(cuid())
|
|
3266
|
+
userId Int
|
|
3267
|
+
roleId String
|
|
3268
|
+
createdAt DateTime @default(now())
|
|
3269
|
+
|
|
3270
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3271
|
+
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
3272
|
+
|
|
3273
|
+
@@unique([userId, roleId])
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
model AuditLog {
|
|
3277
|
+
id String @id @default(cuid())
|
|
3278
|
+
actorId Int?
|
|
3279
|
+
action String
|
|
3280
|
+
entityType String
|
|
3281
|
+
entityId String?
|
|
3282
|
+
details String?
|
|
3283
|
+
severity AuditSeverity @default(INFO)
|
|
3284
|
+
ipAddress String?
|
|
3285
|
+
createdAt DateTime @default(now())
|
|
3286
|
+
|
|
3287
|
+
actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)
|
|
3288
|
+
|
|
3289
|
+
@@index([actorId])
|
|
3290
|
+
@@index([entityType, createdAt])
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
model PromotionCode {
|
|
3294
|
+
id String @id @default(cuid())
|
|
3295
|
+
code String @unique
|
|
3296
|
+
createdById Int?
|
|
3297
|
+
applicablePlanId String?
|
|
3298
|
+
promotionType PromotionType
|
|
3299
|
+
value Float
|
|
3300
|
+
maxUses Int?
|
|
3301
|
+
usageCount Int @default(0)
|
|
3302
|
+
active Boolean @default(true)
|
|
3303
|
+
startsAt DateTime?
|
|
3304
|
+
expiresAt DateTime?
|
|
3305
|
+
metadata Json?
|
|
3306
|
+
createdAt DateTime @default(now())
|
|
3307
|
+
updatedAt DateTime @updatedAt
|
|
3308
|
+
|
|
3309
|
+
createdBy User? @relation("PromotionCodeCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
|
3310
|
+
applicablePlan SubscriptionPlan? @relation(fields: [applicablePlanId], references: [id], onDelete: SetNull)
|
|
3311
|
+
subscriptions UserSubscription[]
|
|
3312
|
+
|
|
3313
|
+
@@index([createdById])
|
|
3314
|
+
@@index([applicablePlanId])
|
|
3315
|
+
@@index([active, expiresAt])
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
model SubscriptionPlan {
|
|
3319
|
+
id String @id @default(cuid())
|
|
3320
|
+
name String
|
|
3321
|
+
description String?
|
|
3322
|
+
price Float
|
|
3323
|
+
interval BillingInterval
|
|
3324
|
+
active Boolean @default(true)
|
|
3325
|
+
features Json?
|
|
3326
|
+
createdAt DateTime @default(now())
|
|
3327
|
+
updatedAt DateTime @updatedAt
|
|
3328
|
+
|
|
3329
|
+
subscriptions UserSubscription[]
|
|
3330
|
+
promotionCodes PromotionCode[]
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
model UserSubscription {
|
|
3334
|
+
id String @id @default(cuid())
|
|
3335
|
+
userId Int
|
|
3336
|
+
planId String
|
|
3337
|
+
promotionCodeId String?
|
|
3338
|
+
status SubscriptionStatus @default(TRIALING)
|
|
3339
|
+
startedAt DateTime @default(now())
|
|
3340
|
+
currentPeriodEnd DateTime?
|
|
3341
|
+
cancelledAt DateTime?
|
|
3342
|
+
metadata Json?
|
|
3343
|
+
|
|
3344
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3345
|
+
plan SubscriptionPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
|
|
3346
|
+
promotionCode PromotionCode? @relation(fields: [promotionCodeId], references: [id], onDelete: SetNull)
|
|
3347
|
+
paymentTransactions PaymentTransaction[]
|
|
3348
|
+
|
|
3349
|
+
@@index([userId, status])
|
|
3350
|
+
@@index([planId])
|
|
3351
|
+
@@index([promotionCodeId])
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
model PaymentTransaction {
|
|
3355
|
+
id String @id @default(cuid())
|
|
3356
|
+
userId Int
|
|
3357
|
+
subscriptionId String?
|
|
3358
|
+
amount Float
|
|
3359
|
+
currency String @default("USD")
|
|
3360
|
+
status PaymentStatus @default(PENDING)
|
|
3361
|
+
provider String?
|
|
3362
|
+
reference String? @unique
|
|
3363
|
+
description String?
|
|
3364
|
+
createdAt DateTime @default(now())
|
|
3365
|
+
updatedAt DateTime @updatedAt
|
|
3366
|
+
|
|
3367
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3368
|
+
subscription UserSubscription? @relation(fields: [subscriptionId], references: [id], onDelete: SetNull)
|
|
3369
|
+
refunds RefundRequest[]
|
|
3370
|
+
|
|
3371
|
+
@@index([userId, createdAt])
|
|
3372
|
+
@@index([subscriptionId])
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
model RefundRequest {
|
|
3376
|
+
id String @id @default(cuid())
|
|
3377
|
+
requesterId Int
|
|
3378
|
+
transactionId String
|
|
3379
|
+
reason String
|
|
3380
|
+
status RefundStatus @default(REQUESTED)
|
|
3381
|
+
requestedAt DateTime @default(now())
|
|
3382
|
+
resolvedAt DateTime?
|
|
3383
|
+
|
|
3384
|
+
requester User @relation("RefundRequester", fields: [requesterId], references: [id], onDelete: Cascade)
|
|
3385
|
+
transaction PaymentTransaction @relation(fields: [transactionId], references: [id], onDelete: Cascade)
|
|
3386
|
+
|
|
3387
|
+
@@index([requesterId])
|
|
3388
|
+
@@index([transactionId])
|
|
3389
|
+
}
|
|
3390
|
+
|
|
3391
|
+
model ApiKey {
|
|
3392
|
+
id String @id @default(cuid())
|
|
3393
|
+
name String
|
|
3394
|
+
keyPrefix String @unique
|
|
3395
|
+
secretHash String
|
|
3396
|
+
status String
|
|
3397
|
+
createdById Int?
|
|
3398
|
+
lastUsedAt DateTime?
|
|
3399
|
+
expiresAt DateTime?
|
|
3400
|
+
createdAt DateTime @default(now())
|
|
3401
|
+
|
|
3402
|
+
@@index([createdById])
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
model WebhookEndpoint {
|
|
3406
|
+
id String @id @default(cuid())
|
|
3407
|
+
name String
|
|
3408
|
+
url String
|
|
3409
|
+
secretHash String?
|
|
3410
|
+
events Json
|
|
3411
|
+
enabled Boolean @default(true)
|
|
3412
|
+
createdById Int?
|
|
3413
|
+
createdAt DateTime @default(now())
|
|
3414
|
+
updatedAt DateTime @updatedAt
|
|
3415
|
+
|
|
3416
|
+
deliveries WebhookDelivery[]
|
|
3417
|
+
|
|
3418
|
+
@@index([createdById])
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
|
+
model WebhookDelivery {
|
|
3422
|
+
id String @id @default(cuid())
|
|
3423
|
+
endpointId String
|
|
3424
|
+
eventType String
|
|
3425
|
+
payload Json
|
|
3426
|
+
responseCode Int?
|
|
3427
|
+
deliveredAt DateTime?
|
|
3428
|
+
status String
|
|
3429
|
+
createdAt DateTime @default(now())
|
|
3430
|
+
|
|
3431
|
+
endpoint WebhookEndpoint @relation(fields: [endpointId], references: [id], onDelete: Cascade)
|
|
3432
|
+
|
|
3433
|
+
@@index([endpointId, createdAt])
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
model Integration {
|
|
3437
|
+
id String @id @default(cuid())
|
|
3438
|
+
name String
|
|
3439
|
+
category String?
|
|
3440
|
+
status String
|
|
3441
|
+
apiVersion String?
|
|
3442
|
+
environment DeploymentEnvironment?
|
|
3443
|
+
dataPoints Int @default(0)
|
|
3444
|
+
healthScore Int?
|
|
3445
|
+
config Json?
|
|
3446
|
+
lastSyncAt DateTime?
|
|
3447
|
+
lastHealthAt DateTime?
|
|
3448
|
+
createdAt DateTime @default(now())
|
|
3449
|
+
updatedAt DateTime @updatedAt
|
|
3450
|
+
}
|
|
3451
|
+
|
|
3452
|
+
model Plugin {
|
|
3453
|
+
id String @id @default(cuid())
|
|
3454
|
+
name String @unique
|
|
3455
|
+
version String
|
|
3456
|
+
latestVersion String?
|
|
3457
|
+
author String?
|
|
3458
|
+
category String?
|
|
3459
|
+
description String?
|
|
3460
|
+
status String?
|
|
3461
|
+
installed Boolean @default(false)
|
|
3462
|
+
enabled Boolean @default(false)
|
|
3463
|
+
hasUpdate Boolean @default(false)
|
|
3464
|
+
rating Float?
|
|
3465
|
+
downloads Int @default(0)
|
|
3466
|
+
priceLabel String?
|
|
3467
|
+
featured Boolean @default(false)
|
|
3468
|
+
marketplaceUrl String?
|
|
3469
|
+
config Json?
|
|
3470
|
+
createdAt DateTime @default(now())
|
|
3471
|
+
updatedAt DateTime @updatedAt
|
|
3472
|
+
|
|
3473
|
+
@@index([category, status])
|
|
3474
|
+
}
|
|
3475
|
+
|
|
3476
|
+
model BackupStorageLocation {
|
|
3477
|
+
id String @id @default(cuid())
|
|
3478
|
+
name String
|
|
3479
|
+
type String
|
|
3480
|
+
path String
|
|
3481
|
+
status String
|
|
3482
|
+
region String?
|
|
3483
|
+
usedBytes Int?
|
|
3484
|
+
totalBytes Int?
|
|
3485
|
+
metadata Json?
|
|
3486
|
+
createdAt DateTime @default(now())
|
|
3487
|
+
updatedAt DateTime @updatedAt
|
|
3488
|
+
|
|
3489
|
+
backupJobs BackupJob[]
|
|
3490
|
+
backupSchedules BackupSchedule[]
|
|
3491
|
+
restoreRuns BackupRestoreRun[]
|
|
3492
|
+
|
|
3493
|
+
@@index([type, status])
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
model BackupSchedule {
|
|
3497
|
+
id String @id @default(cuid())
|
|
3498
|
+
name String
|
|
3499
|
+
backupType BackupType
|
|
3500
|
+
scheduleExpression String
|
|
3501
|
+
nextRunAt DateTime?
|
|
3502
|
+
enabled Boolean @default(true)
|
|
3503
|
+
retentionDays Int?
|
|
3504
|
+
compressionEnabled Boolean @default(true)
|
|
3505
|
+
encryptionEnabled Boolean @default(true)
|
|
3506
|
+
storageLocationId String?
|
|
3507
|
+
createdAt DateTime @default(now())
|
|
3508
|
+
updatedAt DateTime @updatedAt
|
|
3509
|
+
|
|
3510
|
+
storageLocation BackupStorageLocation? @relation(fields: [storageLocationId], references: [id], onDelete: SetNull)
|
|
3511
|
+
backupJobs BackupJob[]
|
|
3512
|
+
|
|
3513
|
+
@@index([storageLocationId])
|
|
3514
|
+
@@index([enabled, nextRunAt])
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3517
|
+
model BackupJob {
|
|
3518
|
+
id String @id @default(cuid())
|
|
3519
|
+
name String
|
|
3520
|
+
backupType BackupType?
|
|
3521
|
+
status String
|
|
3522
|
+
location String?
|
|
3523
|
+
sizeBytes Int?
|
|
3524
|
+
durationSeconds Int?
|
|
3525
|
+
retentionDays Int?
|
|
3526
|
+
compressed Boolean @default(false)
|
|
3527
|
+
encrypted Boolean @default(false)
|
|
3528
|
+
storageLocationId String?
|
|
3529
|
+
scheduleId String?
|
|
3530
|
+
startedAt DateTime?
|
|
3531
|
+
completedAt DateTime?
|
|
3532
|
+
metadata Json?
|
|
3533
|
+
createdAt DateTime @default(now())
|
|
3534
|
+
|
|
3535
|
+
storageLocation BackupStorageLocation? @relation(fields: [storageLocationId], references: [id], onDelete: SetNull)
|
|
3536
|
+
schedule BackupSchedule? @relation(fields: [scheduleId], references: [id], onDelete: SetNull)
|
|
3537
|
+
restores BackupRestoreRun[]
|
|
3538
|
+
|
|
3539
|
+
@@index([storageLocationId])
|
|
3540
|
+
@@index([scheduleId])
|
|
3541
|
+
@@index([backupType, createdAt])
|
|
3542
|
+
}
|
|
3543
|
+
|
|
3544
|
+
model BackupRestoreRun {
|
|
3545
|
+
id String @id @default(cuid())
|
|
3546
|
+
backupJobId String?
|
|
3547
|
+
storageLocationId String?
|
|
3548
|
+
initiatedById Int?
|
|
3549
|
+
targetEnvironment DeploymentEnvironment?
|
|
3550
|
+
status String
|
|
3551
|
+
notes String?
|
|
3552
|
+
startedAt DateTime @default(now())
|
|
3553
|
+
completedAt DateTime?
|
|
3554
|
+
|
|
3555
|
+
backupJob BackupJob? @relation(fields: [backupJobId], references: [id], onDelete: SetNull)
|
|
3556
|
+
storageLocation BackupStorageLocation? @relation(fields: [storageLocationId], references: [id], onDelete: SetNull)
|
|
3557
|
+
initiatedBy User? @relation("BackupRestoreInitiator", fields: [initiatedById], references: [id], onDelete: SetNull)
|
|
3558
|
+
|
|
3559
|
+
@@index([backupJobId])
|
|
3560
|
+
@@index([storageLocationId])
|
|
3561
|
+
@@index([initiatedById, startedAt])
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3564
|
+
model DataExportJob {
|
|
3565
|
+
id String @id @default(cuid())
|
|
3566
|
+
name String
|
|
3567
|
+
status String
|
|
3568
|
+
format String
|
|
3569
|
+
requestedById Int?
|
|
3570
|
+
filters Json?
|
|
3571
|
+
createdAt DateTime @default(now())
|
|
3572
|
+
completedAt DateTime?
|
|
3573
|
+
|
|
3574
|
+
@@index([requestedById])
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
model GameServerNode {
|
|
3578
|
+
id String @id @default(cuid())
|
|
3579
|
+
name String @unique
|
|
3580
|
+
region String
|
|
3581
|
+
status GameServerStatus @default(HEALTHY)
|
|
3582
|
+
websocketConnections Int @default(0)
|
|
3583
|
+
loadPercent Float?
|
|
3584
|
+
latencyMs Int?
|
|
3585
|
+
throughputPerSecond Int?
|
|
3586
|
+
errorRate Float?
|
|
3587
|
+
metadata Json?
|
|
3588
|
+
lastHeartbeatAt DateTime?
|
|
3589
|
+
createdAt DateTime @default(now())
|
|
3590
|
+
updatedAt DateTime @updatedAt
|
|
3591
|
+
|
|
3592
|
+
metrics GameServerMetricSnapshot[]
|
|
3593
|
+
|
|
3594
|
+
@@index([region, status])
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
model GameServerMetricSnapshot {
|
|
3598
|
+
id String @id @default(cuid())
|
|
3599
|
+
nodeId String
|
|
3600
|
+
websocketConnections Int?
|
|
3601
|
+
loadPercent Float?
|
|
3602
|
+
latencyMs Int?
|
|
3603
|
+
throughputPerSecond Int?
|
|
3604
|
+
errorRate Float?
|
|
3605
|
+
capturedAt DateTime @default(now())
|
|
3606
|
+
|
|
3607
|
+
node GameServerNode @relation(fields: [nodeId], references: [id], onDelete: Cascade)
|
|
3608
|
+
|
|
3609
|
+
@@index([nodeId, capturedAt])
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3612
|
+
model Game {
|
|
3613
|
+
id String @id @default(cuid())
|
|
3614
|
+
hostUserId Int?
|
|
3615
|
+
authorId String
|
|
3616
|
+
code String @unique
|
|
3617
|
+
status GameStatus @default(WAITING)
|
|
3618
|
+
createdAt DateTime @default(now())
|
|
3619
|
+
startedAt DateTime?
|
|
3620
|
+
endedAt DateTime?
|
|
3621
|
+
quizId String
|
|
3622
|
+
|
|
3623
|
+
hostUser User? @relation("HostedGames", fields: [hostUserId], references: [id], onDelete: SetNull)
|
|
3624
|
+
quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade)
|
|
3625
|
+
results GameResult[]
|
|
3626
|
+
|
|
3627
|
+
@@index([quizId])
|
|
3628
|
+
@@index([hostUserId])
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
model GameResult {
|
|
3632
|
+
id String @id @default(cuid())
|
|
3633
|
+
score Int @default(0)
|
|
3634
|
+
correctAnswers Int @default(0)
|
|
3635
|
+
gameId String
|
|
3636
|
+
userId Int
|
|
3637
|
+
createdAt DateTime @default(now())
|
|
3638
|
+
answers Json?
|
|
3639
|
+
|
|
3640
|
+
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
|
|
3641
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3642
|
+
|
|
3643
|
+
@@unique([gameId, userId])
|
|
3644
|
+
@@index([gameId])
|
|
3645
|
+
@@index([userId])
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
model Lobby {
|
|
3649
|
+
id String @id @default(cuid())
|
|
3650
|
+
code String @unique
|
|
3651
|
+
hostId Int
|
|
3652
|
+
quizId String
|
|
3653
|
+
name String?
|
|
3654
|
+
mode LobbyMode @default(COMPETITIVE)
|
|
3655
|
+
region String?
|
|
3656
|
+
isPrivate Boolean @default(false)
|
|
3657
|
+
maxPlayers Int @default(15)
|
|
3658
|
+
waitingSince DateTime?
|
|
3659
|
+
spectatorsCount Int @default(0)
|
|
3660
|
+
status LobbyStatus @default(WAITING)
|
|
3661
|
+
createdAt DateTime @default(now())
|
|
3662
|
+
startedAt DateTime?
|
|
3663
|
+
endedAt DateTime?
|
|
3664
|
+
|
|
3665
|
+
host User @relation("HostedLobbies", fields: [hostId], references: [id], onDelete: Cascade)
|
|
3666
|
+
quiz Quiz @relation(fields: [quizId], references: [id], onDelete: Cascade)
|
|
3667
|
+
participants Participant[]
|
|
3668
|
+
|
|
3669
|
+
@@index([quizId])
|
|
3670
|
+
@@index([hostId])
|
|
3671
|
+
@@map("lobbies")
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
model Participant {
|
|
3675
|
+
id Int @id @default(autoincrement())
|
|
3676
|
+
lobbyId String
|
|
3677
|
+
userId Int
|
|
3678
|
+
displayUsername String?
|
|
3679
|
+
avatar String?
|
|
3680
|
+
kicked Boolean? @default(false)
|
|
3681
|
+
status ParticipantStatus @default(LOADING)
|
|
3682
|
+
banReason String?
|
|
3683
|
+
banExpires DateTime?
|
|
3684
|
+
finalScore Int @default(0)
|
|
3685
|
+
rank Int?
|
|
3686
|
+
joinedAt DateTime @default(now())
|
|
3687
|
+
|
|
3688
|
+
lobby Lobby @relation(fields: [lobbyId], references: [id], onDelete: Cascade)
|
|
3689
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3690
|
+
|
|
3691
|
+
@@unique([lobbyId, userId])
|
|
3692
|
+
@@index([userId])
|
|
3693
|
+
@@map("participants")
|
|
3694
|
+
}
|
|
3695
|
+
|
|
3696
|
+
model TrivitEvent {
|
|
3697
|
+
id String @id @default(cuid())
|
|
3698
|
+
hostId Int?
|
|
3699
|
+
subjectId String?
|
|
3700
|
+
title String
|
|
3701
|
+
description String?
|
|
3702
|
+
lobbyCode String? @unique
|
|
3703
|
+
status TrivitStatus @default(DRAFT)
|
|
3704
|
+
scheduledAt DateTime?
|
|
3705
|
+
startedAt DateTime?
|
|
3706
|
+
endedAt DateTime?
|
|
3707
|
+
maxPlayers Int?
|
|
3708
|
+
config Json?
|
|
3709
|
+
createdAt DateTime @default(now())
|
|
3710
|
+
updatedAt DateTime @updatedAt
|
|
3711
|
+
|
|
3712
|
+
host User? @relation("HostedTrivits", fields: [hostId], references: [id], onDelete: SetNull)
|
|
3713
|
+
subject Subject? @relation(fields: [subjectId], references: [id], onDelete: SetNull)
|
|
3714
|
+
participants TrivitParticipant[]
|
|
3715
|
+
|
|
3716
|
+
@@index([hostId])
|
|
3717
|
+
@@index([subjectId])
|
|
3718
|
+
@@index([status, scheduledAt])
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
model TrivitParticipant {
|
|
3722
|
+
id String @id @default(cuid())
|
|
3723
|
+
trivitId String
|
|
3724
|
+
userId Int
|
|
3725
|
+
score Int @default(0)
|
|
3726
|
+
accuracy Float?
|
|
3727
|
+
rank Int?
|
|
3728
|
+
joinedAt DateTime @default(now())
|
|
3729
|
+
|
|
3730
|
+
trivit TrivitEvent @relation(fields: [trivitId], references: [id], onDelete: Cascade)
|
|
3731
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
3732
|
+
|
|
3733
|
+
@@unique([trivitId, userId])
|
|
3734
|
+
@@index([userId])
|
|
3735
|
+
}
|