@adaptware/eagles-db 0.1.26 → 0.1.30

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.
@@ -0,0 +1,1166 @@
1
+ model CandidateQuestionResponse {
2
+ id String @id @default(uuid())
3
+ question_id String
4
+ candidate_id String
5
+ assessment_id String
6
+ response String
7
+ score Float?
8
+ created_by String
9
+ updated_by String
10
+ created_at DateTime @default(now())
11
+ updated_at DateTime @updatedAt
12
+ is_active Boolean @default(true)
13
+ // Relations
14
+ question Question @relation(fields: [question_id], references: [id], onDelete: Cascade)
15
+ assessment Assessment @relation(fields: [assessment_id], references: [id], onDelete: Cascade)
16
+ candidate User @relation(fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
17
+
18
+ @@index([candidate_id])
19
+ @@index([question_id])
20
+ @@index([assessment_id])
21
+ }
22
+
23
+ model UserRole {
24
+ id String @id @default(uuid())
25
+ role String
26
+ organisation_id String?
27
+ is_custom Boolean @default(false)
28
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
29
+ permission_id String? @unique
30
+ permission Permission? @relation(fields: [permission_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
31
+ users User[]
32
+ created_at DateTime @default(now())
33
+ updated_at DateTime @updatedAt
34
+ created_by String
35
+ updated_by String
36
+ is_active Boolean @default(true)
37
+
38
+ @@unique([role, organisation_id])
39
+ @@index([role, organisation_id])
40
+ @@index([organisation_id])
41
+ @@index([permission_id])
42
+ }
43
+
44
+ enum ActionType {
45
+ TAKE_INTERVIEW
46
+ PROVIDE_FEEDBACK
47
+ SCHEDULE_INTERVIEW
48
+ }
49
+
50
+ enum ActionStatus {
51
+ PENDING
52
+ COMPLETED
53
+ CANCELLED
54
+ }
55
+
56
+ model Action {
57
+ id String @id @default(uuid())
58
+ assignee_id String
59
+ title String
60
+ action_type ActionType
61
+ action_id String // Generic foreign key that can link to any entity
62
+ due_date DateTime?
63
+ organisation_id String
64
+ status ActionStatus @default(PENDING)
65
+ // Relations
66
+ user User @relation(fields: [assignee_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
67
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
68
+ // Audit fields
69
+ created_at DateTime @default(now())
70
+ updated_at DateTime @updatedAt
71
+ created_by String
72
+ updated_by String
73
+ is_active Boolean @default(true)
74
+
75
+ @@index([assignee_id, action_type])
76
+ @@index([status])
77
+ @@index([due_date])
78
+ }
79
+
80
+ // PENDING could be understood as unscreened
81
+ enum ApplicationStatus {
82
+ PENDING
83
+ IN_PROGRESS
84
+ SHORTLISTED
85
+ REJECTED
86
+ }
87
+
88
+ model Application {
89
+ id String @id @default(uuid())
90
+ candidate_id String
91
+ resume_id String
92
+ organisation_id String
93
+ job_description_id String
94
+ status ApplicationStatus @default(PENDING)
95
+ fit_check_score Float?
96
+ fit_check_status FitCheckStatus?
97
+ applied_at DateTime @default(now())
98
+ evaluation_plan_id String?
99
+ evaluation_plan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id])
100
+ fit_check_id String? @unique
101
+ round_no Int @default(0)
102
+
103
+ // Relations
104
+ candidate User @relation(fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
105
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
106
+ resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
107
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
108
+ fit_check FitCheck? @relation(fields: [fit_check_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
109
+ interviews Interview[]
110
+ ongoing_evaluations OngoingEvaluation[]
111
+
112
+ created_at DateTime @default(now())
113
+ updated_at DateTime @updatedAt
114
+ created_by String
115
+ updated_by String
116
+ is_active Boolean @default(true)
117
+
118
+ @@unique([candidate_id, job_description_id]) // Ensures candidate applies only once per job
119
+ @@index([candidate_id])
120
+ @@index([job_description_id])
121
+ @@index([organisation_id])
122
+ @@index([resume_id])
123
+ }
124
+
125
+ model Approval {
126
+ id String @id @default(uuid())
127
+ job_description_id String
128
+ user_id String
129
+ organisaton_id String
130
+ created_at DateTime @default(now())
131
+ updated_at DateTime @updatedAt
132
+ created_by String
133
+ updated_by String
134
+ is_active Boolean @default(true)
135
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
136
+ user User @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
137
+ organisation Organisation @relation(fields: [organisaton_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
138
+ }
139
+
140
+ enum AssessmentStatus {
141
+ SCHEDULED // Assessment has been created and scheduled
142
+ IN_PROGRESS // Candidate is currently giving the assessment
143
+ COMPLETED // Assessment completed by candidate
144
+ CANCELLED // Assessment cancelled by admin or system
145
+ RESCHEDULED // Assessment rescheduled to a new time
146
+ NO_SHOW // Candidate failed to take the assessment
147
+ EVALUATION_PENDING // Waiting for manual/AI review of answers
148
+ EVALUATED // Final evaluation completed and locked
149
+ }
150
+
151
+ model Assessment {
152
+ id String @id @default(uuid())
153
+ assessment_id String
154
+ candidate_id String
155
+ reviewer_id String?
156
+ score Float?
157
+ feedback String?
158
+ scheduled_start_time DateTime? @default(now()) // Start Time to start the assessment
159
+ assessment_status AssessmentStatus @default(SCHEDULED)
160
+ created_at DateTime @default(now())
161
+ updated_at DateTime @updatedAt
162
+ created_by String
163
+ updated_by String
164
+ is_active Boolean @default(true)
165
+ // Relations
166
+ assessment_libarary AssessmentLibrary @relation(fields: [assessment_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
167
+ candidate User @relation("CandidateAssessments", fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
168
+ reviewer User? @relation("ReviewerAssessments", fields: [reviewer_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
169
+ questions AssessmentQuestion[] @relation("AssessmentToAssessmentQuestion")
170
+ candidateResponse CandidateQuestionResponse[]
171
+ Panelist Panelist? @relation(fields: [panelistId], references: [id])
172
+ panelistId String?
173
+ User User? @relation(fields: [userId], references: [id])
174
+ userId String?
175
+
176
+ @@unique([assessment_id, candidate_id])
177
+ @@index([assessment_id])
178
+ @@index([candidate_id])
179
+ }
180
+
181
+ /// Defines how an assessment is conducted.
182
+
183
+ enum AssessmentCategory {
184
+ MCQ
185
+ COMPETENCY
186
+ CASE_STUDY
187
+ ASSIGNMENT
188
+ }
189
+
190
+ model AssessmentLibrary {
191
+ id String @id @default(uuid())
192
+ title String
193
+ assessment_type String?
194
+ description String?
195
+ assessment_category AssessmentCategory
196
+ time_required Int
197
+ passing_score Float?
198
+ max_score Float?
199
+ organisation_id String
200
+ created_by_ai Boolean @default(false)
201
+ created_at DateTime @default(now())
202
+ updated_at DateTime @updatedAt
203
+ created_by String
204
+ updated_by String
205
+ is_active Boolean @default(true)
206
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
207
+ questions Question[] // One assessment → many questions
208
+ assessments Assessment[]
209
+ evaluation_Plans EvaluationPlan[]
210
+
211
+ @@index([organisation_id])
212
+ @@index([created_at])
213
+ }
214
+
215
+ /**
216
+ * Join table linking Assessments and Questions in a many-to-many relationship.
217
+ * - Each row represents one link between a specific Assessment and a specific Question.
218
+ * - Composite ID ensures no duplicate pairings exist.
219
+ * - Cascade delete ensures join rows are removed when either side is deleted.
220
+ * - Enables sharing the same Question across multiple Assessments.
221
+ */
222
+ model AssessmentQuestion {
223
+ assessment_id String
224
+ question_id String
225
+ assessment Assessment @relation("AssessmentToAssessmentQuestion", fields: [assessment_id], references: [id], onDelete: Cascade)
226
+ question Question @relation("QuestionToAssessmentQuestion", fields: [question_id], references: [id], onDelete: Cascade)
227
+ created_at DateTime @default(now())
228
+ updated_at DateTime @updatedAt
229
+
230
+ @@id([assessment_id, question_id])
231
+ }
232
+
233
+ model AssignmentLibrary {
234
+ id String @id @default(uuid())
235
+ deadline Int
236
+ /// Flexible JSON for assignment-specific config (rubrics, instructions, criteria, etc.)
237
+ assignment Json?
238
+ job_description_id String
239
+ organisation_id String
240
+ created_at DateTime @default(now())
241
+ updated_at DateTime @updatedAt
242
+ created_by String
243
+ updated_by String
244
+ is_active Boolean @default(true)
245
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
246
+ jobDescription JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
247
+ /// Back-relation: one-to-one from EvaluationPlan (FK lives on EvaluationPlan.assignment_library_id)
248
+ evaluationPlan EvaluationPlan[]
249
+
250
+ @@index([job_description_id])
251
+ @@index([created_at])
252
+ }
253
+
254
+ enum JobType {
255
+ Full_time
256
+ Part_time
257
+ Contract
258
+ Internship
259
+ Temporary
260
+ }
261
+
262
+ enum JDCreationType {
263
+ Pick_from_Library
264
+ Upload_JD
265
+ Create_New
266
+ Create_From_Profile
267
+ }
268
+
269
+ model Budget {
270
+ id String @id @default(uuid())
271
+ job_type JobType
272
+ location String
273
+ shift String
274
+ openings Int
275
+ budget_per_job String
276
+ level String
277
+ start_date DateTime
278
+ closing_date DateTime
279
+ business_unit String
280
+ purpose String
281
+ role String
282
+ domain String
283
+ jd_creation_type JDCreationType
284
+ job_description_id String @unique
285
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
286
+ created_at DateTime @default(now())
287
+ updated_at DateTime @updatedAt
288
+ created_by String
289
+ updated_by String
290
+ is_active Boolean @default(true)
291
+ }
292
+
293
+ model Calendly {
294
+ id String @id @default(uuid())
295
+ user_id String @unique
296
+
297
+ access_token String
298
+ refresh_token String
299
+ expires_at DateTime
300
+ calendly_user_uri String
301
+ scope String?
302
+
303
+ user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
304
+
305
+ created_at DateTime @default(now())
306
+ updated_at DateTime @updatedAt
307
+ created_by String
308
+ updated_by String
309
+ is_active Boolean @default(true)
310
+ }
311
+
312
+ model CandidateProfile {
313
+ id String @id @default(uuid())
314
+ created_at DateTime @default(now())
315
+ updated_at DateTime @updatedAt
316
+ name String
317
+ phone String
318
+ location String
319
+ salary String?
320
+ description String?
321
+ resume_id String? @unique
322
+ date_of_birth DateTime?
323
+
324
+ user User? @relation(fields: [user_id], references: [id])
325
+ user_id String? @unique
326
+
327
+ resume Resume? @relation(fields: [resume_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
328
+
329
+ work_experience Json?
330
+ education Json?
331
+ notice_period String?
332
+ gender String?
333
+ ethnicity String?
334
+ veteran_status String?
335
+ disability_status String?
336
+ is_active Boolean @default(true)
337
+ }
338
+
339
+ model ContactUs {
340
+ id String @id @default(uuid())
341
+ name String
342
+ email String
343
+ organisation_name String
344
+ organisation_website String
345
+ subject String
346
+ message String
347
+ createdAt DateTime @default(now())
348
+ updatedAt DateTime @updatedAt
349
+ is_active Boolean @default(true)
350
+ }
351
+
352
+ enum RoundType {
353
+ ASSESSMENT
354
+ INTERVIEW
355
+ ASSIGNMENT
356
+ SCREENING
357
+ }
358
+
359
+ enum EvaluationRoundFormat {
360
+ // ────────────────
361
+ // Screening formats
362
+ // ────────────────
363
+ PHONE_CALL
364
+ VIDEO_CALL_AI_ASSISTED
365
+ VIDEO_CALL_UNASSISTED
366
+
367
+ // ────────────────
368
+ // Assessment formats
369
+ // ────────────────
370
+ AI_GENERATED_TEST
371
+ UPLOADED_TEST
372
+ EXTERNAL_PLATFORM
373
+
374
+ // ────────────────
375
+ // Assignment formats
376
+ // ────────────────
377
+ AI_GENERATED_ASSIGNMENT
378
+ UPLOADED_ASSIGNMENT
379
+
380
+ // ────────────────
381
+ // Interview formats
382
+ // ────────────────
383
+ TREADSPACE_AI_ASSISTED
384
+ EXTERNAL_VIDEO_AI_ASSISTED
385
+ EXTERNAL_VIDEO_UNASSISTED
386
+ }
387
+
388
+ enum EvaluationType {
389
+ // New (In active use now)
390
+ TREADSPACE_AI_ASSISTED
391
+ EXTERNAL_AI_ASSISTED
392
+ NON_AI_ASSISTED
393
+ }
394
+
395
+ enum EvaluationPlanType {
396
+ CUSTOM
397
+ GENERIC
398
+ DELETED
399
+ }
400
+
401
+ model EvaluationPlan {
402
+ id String @id @default(uuid())
403
+ job_description_id String
404
+ assessment_id String?
405
+ assignment_library_id String?
406
+ title String
407
+ description String?
408
+ format EvaluationRoundFormat?
409
+ topics String[]
410
+ assignee String?
411
+ elimination_round Boolean @default(false)
412
+ evaluation_type EvaluationType
413
+ type_of_round RoundType
414
+ timeline Int
415
+ order_no Int?
416
+ details Json?
417
+ plan_type EvaluationPlanType @default(GENERIC)
418
+ created_by String
419
+ updated_by String
420
+ created_at DateTime @default(now())
421
+ updated_at DateTime @updatedAt
422
+ is_active Boolean @default(true)
423
+ // Relations
424
+ jobDescription JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade)
425
+ questions Question[] // One evaluation plan → many questions
426
+ panelists Panelist[]
427
+ interviews Interview[]
428
+ applications Application[]
429
+ // New optional one-to-one relation with AssessmentLibrary
430
+ assessment AssessmentLibrary? @relation(fields: [assessment_id], references: [id], onDelete: SetNull)
431
+ assignment_library AssignmentLibrary? @relation(fields: [assignment_library_id], references: [id], onDelete: SetNull)
432
+ ongoing_evaluations OngoingEvaluation[]
433
+
434
+ @@unique([job_description_id, order_no])
435
+ @@index([job_description_id])
436
+ }
437
+
438
+ model Feedback {
439
+ id String @id @default(uuid())
440
+ interview_id String
441
+ order_no Int
442
+
443
+ ai_feedback Json?
444
+ human_feedback Json?
445
+
446
+ created_at DateTime @default(now())
447
+ updated_at DateTime @updatedAt
448
+ created_by String
449
+ updated_by String
450
+ is_active Boolean @default(true)
451
+ interview Interview @relation(fields: [interview_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
452
+
453
+ @@unique([interview_id, order_no])
454
+ @@index([interview_id])
455
+ }
456
+
457
+ enum FitCheckStatus {
458
+ RECOMMENDED
459
+ TO_REVIEW
460
+ NOT_RECOMMENDED
461
+ }
462
+
463
+ model FitCheck {
464
+ /// Primary key (UUID)
465
+ id String @id @default(uuid())
466
+ /// FK to organisations table
467
+ organisation_id String?
468
+ resume_id String
469
+ job_description_id String
470
+
471
+ /// Old Fields will be deprecated soon
472
+ skills_match String[]
473
+ skills_score Float?
474
+ responsibilities_match String[]
475
+ responsibilities_score Float?
476
+ experience_match String[]
477
+ experience_score Float?
478
+ organisation_value_score Float?
479
+ organisation_value_match String[]
480
+ qualifications_match String[]
481
+ qualifications_score Float?
482
+ overall_analysis String[]
483
+ fit Json[]
484
+ fit_check_status FitCheckStatus?
485
+ // Fields to be used now
486
+
487
+ overall_score Float
488
+ short_match_analysis Json[]
489
+ candidate_analysis Json[]
490
+ technical_analysis Json[]
491
+ competency_analysis Json[]
492
+ recommendation Json?
493
+
494
+ /// Audit fields
495
+ created_by String
496
+ updated_by String
497
+ is_active Boolean @default(true)
498
+ /// Timestamps
499
+ created_at DateTime @default(now())
500
+ updated_at DateTime @updatedAt
501
+ /// Relations
502
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
503
+ resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
504
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
505
+ application Application?
506
+
507
+ /// Ensure one FitCheck per (resume_id, job_description_id) pair
508
+ @@unique([resume_id, job_description_id])
509
+ @@index([resume_id])
510
+ }
511
+
512
+ model Google {
513
+ id String @id @default(uuid())
514
+ user_id String @unique
515
+
516
+ google_email String
517
+ refresh_token String
518
+ scope String?
519
+
520
+ user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
521
+
522
+ created_at DateTime @default(now())
523
+ updated_at DateTime @updatedAt
524
+ created_by String
525
+ updated_by String
526
+ is_active Boolean @default(true)
527
+ }
528
+
529
+ model IntermediateFeedback {
530
+ id String @id @default(uuid())
531
+ interview_id String
532
+ overall_feedback_id String?
533
+ intermediate_feedback Json
534
+ order_no Int @default(autoincrement())
535
+ created_at DateTime @default(now())
536
+ updated_at DateTime @updatedAt
537
+ created_by String
538
+ updated_by String
539
+ is_active Boolean @default(true)
540
+ // Relations
541
+ interview Interview @relation(fields: [interview_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
542
+ OverallFeedback OverallFeedback? @relation(fields: [overall_feedback_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
543
+ transcripts Transcript[]
544
+
545
+ @@index([interview_id])
546
+ }
547
+
548
+ enum InterviewStatus {
549
+ INTERVIEW_REQUESTED
550
+ SCHEDULED
551
+ IN_PROGRESS
552
+ CANCELLED
553
+ NO_SHOW // Candidate or interviewer failed to appear
554
+ EVALUATION_PENDING // Waiting for feedback or evaluation
555
+ EVALUATED // Feedback completed and locked
556
+ }
557
+
558
+ enum InterviewFeedback {
559
+ STRONG_HIRE
560
+ HIRE
561
+ NO_HIRE
562
+ STRONG_NO_HIRE
563
+ }
564
+
565
+ model Interview {
566
+ id String @id @default(uuid())
567
+ candidate_id String
568
+ interviewer_id String?
569
+ evaluation_plan_id String
570
+ application_id String?
571
+ resume_id String
572
+ job_description_id String
573
+ organisation_id String
574
+ room_name String?
575
+ interview_summary String[]
576
+ ai_interview_feedback InterviewFeedback?
577
+ interview_feedback InterviewFeedback?
578
+ interview_rating Float? // Overall rating out of 100 based on evaluation
579
+ scheduled_start_time DateTime?
580
+ scheduled_end_time DateTime?
581
+ actual_start_time DateTime?
582
+ actual_end_time DateTime?
583
+ recording_url String?
584
+ interview_status InterviewStatus @default(SCHEDULED)
585
+ google_event_id String?
586
+ created_at DateTime @default(now())
587
+ updated_at DateTime @updatedAt
588
+ created_by String
589
+ updated_by String
590
+ is_active Boolean @default(true)
591
+ // Relations
592
+ candidate User? @relation("CandidateInterviews", fields: [candidate_id], references: [id], onDelete: SetNull)
593
+ interviewer User? @relation("InterviewerInterviews", fields: [interviewer_id], references: [id], onDelete: SetNull)
594
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
595
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
596
+ resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
597
+ evaluation_plan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
598
+ application Application? @relation(fields: [application_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
599
+ ongoing_evaluation OngoingEvaluation?
600
+ intermediateFeedbacks IntermediateFeedback[]
601
+ transcripts Transcript[]
602
+ suggestions Suggestion[]
603
+ overallFeedback OverallFeedback[]
604
+ feedback Feedback[]
605
+ interviewNotes InterviewNotes[]
606
+
607
+ @@unique([interviewer_id, candidate_id, evaluation_plan_id])
608
+ @@index([application_id])
609
+ @@index([candidate_id])
610
+ @@index([interviewer_id])
611
+ @@index([job_description_id])
612
+ }
613
+
614
+ /// Defines the category or purpose of the interview, suitable for any job role.
615
+ enum InterviewCategory {
616
+ SCREENING // Initial screening interview
617
+ TECHNICAL // Skill or role-specific interview
618
+ BEHAVIORAL // Behavioral or situational round
619
+ CASE_STUDY // Case-based or analytical round
620
+ MANAGERIAL // Leadership or management-focused
621
+ CULTURAL_FIT // Checks alignment with company culture
622
+ FINAL_DISCUSSION // Final HR or offer discussion
623
+ GENERAL // Generic or flexible-purpose interview
624
+ }
625
+
626
+ /// Represents a reusable interview template applicable to any job type.
627
+ model InterviewLibrary {
628
+ id String @id @default(uuid())
629
+ title String
630
+ description String
631
+ organisation_id String
632
+ category InterviewCategory
633
+ evaluation_type EvaluationType
634
+ duration Float
635
+ passing_marks Float
636
+ is_active Boolean @default(true)
637
+ created_by String
638
+ updated_by String
639
+ created_at DateTime @default(now())
640
+ updated_at DateTime @updatedAt
641
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
642
+
643
+ @@index([organisation_id])
644
+ @@index([category])
645
+ @@index([created_at])
646
+ }
647
+
648
+ model InterviewNotes {
649
+ id String @id @default(uuid())
650
+ interview_id String
651
+ note String
652
+ details Json?
653
+ timestamp DateTime @default(now())
654
+ created_at DateTime @default(now())
655
+ updated_at DateTime @updatedAt
656
+ created_by String
657
+ updated_by String
658
+ is_active Boolean @default(true)
659
+
660
+ // Relations
661
+ interview Interview @relation(fields: [interview_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
662
+
663
+ @@index([interview_id])
664
+ }
665
+
666
+ enum JobDescriptionStatus {
667
+ CREATED
668
+ DRAFT
669
+ ACTIVE
670
+ DEACTIVATED
671
+ CLOSED
672
+ }
673
+
674
+ model JobDescription {
675
+ id String @id @default(uuid())
676
+ organisation_id String
677
+ hiring_manager_id String?
678
+ status JobDescriptionStatus @default(DRAFT)
679
+ screeningQuestions String[]
680
+ recommendedQuestions Json[]
681
+ uploaded_job_description_path String?
682
+ is_plan_locked Boolean? @default(false)
683
+ is_plan_published Boolean @default(false)
684
+ is_posted Boolean @default(false)
685
+ ai_insight Json?
686
+ // Audit fields
687
+ created_at DateTime @default(now())
688
+ updated_at DateTime @updatedAt
689
+ created_by String
690
+ updated_by String
691
+ is_active Boolean @default(true)
692
+ openings Int @default(1)
693
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
694
+ applications Application[]
695
+ interviews Interview[]
696
+ fit_check FitCheck[] // one-to-many link
697
+ job_description_data JobDescriptionData[] // one-to-many link
698
+ evaluationPlan EvaluationPlan[] // relation to evaluation methods
699
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
700
+ assignment_library AssignmentLibrary[]
701
+ approvals Approval[] // one-to-many relation
702
+ resumes Resume[] // one-to-many link
703
+ budget Budget?
704
+ hiring_manager User? @relation("HiringManager", fields: [hiring_manager_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
705
+ recruiters User[]
706
+ transcripts Transcript[]
707
+
708
+ @@index([organisation_id])
709
+ @@index([hiring_manager_id])
710
+ }
711
+
712
+ model JobDescriptionData {
713
+ id String @id @default(uuid())
714
+ job_description_id String
715
+ key String
716
+ value String
717
+ created_at DateTime @default(now())
718
+ updated_at DateTime @updatedAt
719
+ created_by String
720
+ updated_by String
721
+ is_active Boolean @default(true)
722
+
723
+ jobDescription JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
724
+
725
+ @@unique([job_description_id, key])
726
+ @@index([created_at])
727
+ }
728
+
729
+ model Message {
730
+ id String @id @default(uuid())
731
+ sender_id String
732
+ receiver_id String
733
+ message String
734
+
735
+ sender User @relation("Sent Messages", fields: [sender_id], references: [id])
736
+ receiver User @relation("Received Messages", fields: [receiver_id], references: [id])
737
+
738
+ created_at DateTime @default(now())
739
+ updated_at DateTime @updatedAt
740
+ created_by String
741
+ updated_by String
742
+ is_active Boolean @default(true)
743
+ }
744
+
745
+ enum OngoingEvaluationStatus {
746
+ LOCKED
747
+ ACTION_REQUIRED
748
+ IN_PROGRESS
749
+ EVALUATED
750
+ CLEARED
751
+ NOT_CLEARED
752
+ SKIPPED
753
+ }
754
+
755
+ enum OngoingEvaluationState {
756
+ NOT_STARTED
757
+ IN_PROGRESS
758
+ CLEARED
759
+ SKIPPED
760
+ NOT_CLEARED
761
+ }
762
+
763
+ enum OngoingEvaluationRoundStatus {
764
+ NOT_SCHEDULED
765
+ REQUESTED_SCHEDULING
766
+ SCHEDULED
767
+ IN_PROGRESS
768
+ PENDING_EVALUATION
769
+ EVALUATED
770
+ }
771
+
772
+ model OngoingEvaluation {
773
+ id String @id @default(uuid())
774
+ application_id String
775
+ candidate_id String
776
+ resume_id String
777
+ organisation_id String
778
+ job_description_id String
779
+ evaluation_plan_id String
780
+ interview_id String? @unique
781
+ status OngoingEvaluationStatus?
782
+ state OngoingEvaluationState? @default(NOT_STARTED)
783
+ round_status OngoingEvaluationRoundStatus? @default(NOT_SCHEDULED)
784
+ comments String? @default("")
785
+ // Relations
786
+ jobDescription JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull)
787
+ application Application @relation(fields: [application_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
788
+ candidate User? @relation(fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
789
+ resume Resume? @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
790
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
791
+ evaluation_plan EvaluationPlan @relation(fields: [evaluation_plan_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
792
+ interview Interview? @relation(fields: [interview_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
793
+ created_at DateTime @default(now())
794
+ updated_at DateTime @updatedAt
795
+ created_by String
796
+ updated_by String
797
+ is_active Boolean @default(true)
798
+ is_current Boolean @default(false)
799
+ // Evaluation Plan Details Will be stored only when candidate starts for the evaluation round
800
+ title String?
801
+ description String?
802
+ round_no Int?
803
+ format EvaluationRoundFormat?
804
+ topics String[]
805
+ assignee String?
806
+ elimination_round Boolean? @default(false)
807
+ evaluation_type EvaluationType?
808
+ type_of_round RoundType?
809
+ timeline Int?
810
+ details Json?
811
+
812
+ @@unique([application_id, evaluation_plan_id])
813
+ @@index([application_id])
814
+ @@index([evaluation_plan_id])
815
+ }
816
+
817
+ enum OrganisationSize {
818
+ ONE_TO_TEN @map("1-10")
819
+ ELEVEN_TO_FIFTY @map("11-50")
820
+ FIFTY_ONE_TO_TWO_HUNDRED @map("51-200")
821
+ TWO_HUNDRED_ONE_TO_FIVE_HUNDRED @map("201-500")
822
+ FIVE_HUNDRED_PLUS @map("500+")
823
+ }
824
+
825
+ model Organisation {
826
+ id String @id @default(uuid())
827
+ name String @unique
828
+ industry String
829
+ about String
830
+ website String
831
+ size OrganisationSize @default(ONE_TO_TEN)
832
+ phone String
833
+ address String
834
+ company_values Json[]
835
+
836
+ interviewers User[]
837
+ created_at DateTime @default(now())
838
+ updated_at DateTime @updatedAt
839
+ created_by String
840
+ updated_by String
841
+ is_active Boolean @default(true)
842
+ alias String? @unique
843
+ logo String?
844
+ applications Application[]
845
+ user_roles UserRole[]
846
+ job_descriptions JobDescription[]
847
+ assessment_library AssessmentLibrary[]
848
+ assignment_library AssignmentLibrary[]
849
+ interview_library InterviewLibrary[]
850
+ interviews Interview[]
851
+ fit_check FitCheck[] // one-to-many link
852
+ resumes Resume[] // one-to-many link
853
+ panelists Panelist[] // one-to-many link
854
+ approvals Approval[] // one-to-many link
855
+ suggestions Suggestion[]
856
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
857
+ actions Action[]
858
+
859
+ @@index([name])
860
+ }
861
+
862
+ enum FeedbackType {
863
+ HUMAN
864
+ AI
865
+ }
866
+
867
+ enum OverallRecommendation {
868
+ StrongHire
869
+ Hire
870
+ LeaningHire
871
+ NoHire
872
+ StrongNoHire
873
+ }
874
+
875
+ model OverallFeedback {
876
+ id String @id @default(uuid())
877
+ interview_id String
878
+ interviewer_id String? // 👈 optional field
879
+ feedback_type FeedbackType
880
+ overall_score Float
881
+ overall_recommendation OverallRecommendation
882
+ overall_feedback Json
883
+ created_at DateTime @default(now())
884
+ updated_at DateTime @updatedAt
885
+ created_by String
886
+ updated_by String
887
+ is_active Boolean @default(true)
888
+ // Relations
889
+ interview Interview @relation(fields: [interview_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
890
+ interviewer Panelist? @relation(fields: [interviewer_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
891
+ intermediateFeedbacks IntermediateFeedback[] // 👈 one-to-many relation added here
892
+
893
+ @@unique([interview_id, interviewer_id]) // 👈 updated uniqueness logic
894
+ @@index([interview_id])
895
+ @@index([interviewer_id])
896
+ }
897
+
898
+ model Panelist {
899
+ id String @id @default(uuid())
900
+ name String
901
+ designation String
902
+ experience String // e.g. "10+", keeping as String for flexibility
903
+ expertise String // e.g. "Product Strategy, Figma..."
904
+ suited_interview String // e.g. "Consulting, Customer understanding..."
905
+ industry String // e.g. "Healthcare, Fintech"
906
+ special_areas String? // Optional field
907
+ organisation_id String
908
+ user_id String @unique
909
+
910
+ user User @relation(fields: [user_id], references: [id])
911
+ organisation Organisation @relation(fields: [organisation_id], references: [id])
912
+ evaluationPlans EvaluationPlan[]
913
+ overallFeedbacks OverallFeedback[]
914
+ created_at DateTime @default(now())
915
+ updated_at DateTime @updatedAt
916
+ created_by String
917
+ updated_by String
918
+ is_active Boolean @default(true)
919
+
920
+ assessments Assessment[]
921
+ }
922
+
923
+ model Permission {
924
+ id String @id @default(uuid())
925
+ permissions String[] @default([])
926
+ created_by String?
927
+ updated_by String?
928
+ updated_at DateTime @updatedAt
929
+ created_at DateTime @default(now())
930
+ is_active Boolean @default(true)
931
+ user User?
932
+ user_roles UserRole?
933
+
934
+ @@index([created_at])
935
+ }
936
+
937
+ enum Difficulty {
938
+ EASY // simple/basic questions
939
+ MEDIUM // moderate difficulty
940
+ HARD // challenging questions
941
+ }
942
+
943
+ enum QuestionType {
944
+ MCQ
945
+ TRUE_FALSE
946
+ THEORY
947
+ CODING
948
+ }
949
+
950
+ model Question {
951
+ id String @id @default(uuid())
952
+ assessment_library_id String?
953
+ evaluation_plan_id String?
954
+ candidate_id String?
955
+ skill String?
956
+ question_type QuestionType?
957
+ question String
958
+ answer String
959
+ options String[] // For MCQ's
960
+ max_score Float?
961
+ difficulty Difficulty?
962
+ created_by String
963
+ updated_by String
964
+ created_at DateTime @default(now())
965
+ updated_at DateTime @updatedAt
966
+ is_active Boolean @default(true)
967
+ candidate User? @relation(fields: [candidate_id], references: [id], onDelete: SetNull)
968
+ assessments AssessmentQuestion[] @relation("QuestionToAssessmentQuestion")
969
+ assessmentLibrary AssessmentLibrary? @relation(fields: [assessment_library_id], references: [id], onDelete: Cascade)
970
+ evaluationPlan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id], onDelete: SetNull)
971
+ candidateResponse CandidateQuestionResponse[]
972
+ }
973
+
974
+ model Resume {
975
+ id String @id @default(uuid())
976
+ user_id String?
977
+ organisation_id String?
978
+ job_description_id String?
979
+ uploaded_resume_path String?
980
+ created_at DateTime @default(now())
981
+ updated_at DateTime @updatedAt
982
+ created_by String
983
+ updated_by String
984
+ is_active Boolean @default(true)
985
+ user User? @relation(fields: [user_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
986
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
987
+ job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
988
+ applications Application[]
989
+ interviews Interview[]
990
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
991
+
992
+ resume_data ResumeData[] // one-to-many link
993
+ fit_check FitCheck[] // one-to-many link
994
+ // inverse side of the relation — no foreign key here
995
+ candidate_profile CandidateProfile? // one-to-one link
996
+ yearsOfExperience Int?
997
+
998
+ @@index([user_id])
999
+ }
1000
+
1001
+ model ResumeData {
1002
+ id String @id @default(uuid())
1003
+ resume_id String
1004
+ key String
1005
+ value String
1006
+ created_at DateTime @default(now())
1007
+ updated_at DateTime @updatedAt
1008
+ created_by String
1009
+ updated_by String
1010
+ is_active Boolean @default(true)
1011
+
1012
+ resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
1013
+
1014
+ @@index([created_at])
1015
+ }
1016
+
1017
+ // This is your Prisma schema file,
1018
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
1019
+
1020
+ // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
1021
+ // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
1022
+
1023
+ generator client {
1024
+ provider = "prisma-client-js"
1025
+ output = "../../client"
1026
+ binaryTargets = ["native", "linux-arm64-openssl-1.1.x"]
1027
+ }
1028
+
1029
+ datasource db {
1030
+ provider = "postgresql"
1031
+ url = env("DATABASE_URL")
1032
+ }
1033
+
1034
+ model Suggestion {
1035
+ id String @id @default(uuid())
1036
+ interview_id String?
1037
+ transcript_id String? @unique // ✅ ensures one-to-one
1038
+ organisation_id String
1039
+ suggestion String
1040
+ question String?
1041
+ created_at DateTime @default(now())
1042
+ updated_at DateTime @updatedAt
1043
+ created_by String
1044
+ updated_by String
1045
+ is_active Boolean @default(true)
1046
+
1047
+ // Relations
1048
+ interview Interview? @relation(fields: [interview_id], references: [id], onDelete: SetNull)
1049
+ transcripts Transcript[]
1050
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade)
1051
+
1052
+ @@index([interview_id])
1053
+ @@index([transcript_id])
1054
+ }
1055
+
1056
+ model Transcript {
1057
+ id String @id @default(uuid())
1058
+ interview_id String?
1059
+ suggestion_id String?
1060
+ intermediate_feedback_id String?
1061
+ job_description_id String?
1062
+ interviewer_timestamp DateTime?
1063
+ candidate_timestamp DateTime?
1064
+ interviewer String
1065
+ candidate String
1066
+ order_no Int @default(autoincrement())
1067
+ created_at DateTime @default(now())
1068
+ updated_at DateTime @updatedAt
1069
+ created_by String
1070
+ updated_by String
1071
+ is_active Boolean @default(true)
1072
+ // Relations
1073
+ interview Interview? @relation(fields: [interview_id], references: [id], onDelete: SetNull, onUpdate: SetNull)
1074
+ suggestion Suggestion? @relation(fields: [suggestion_id], references: [id], onDelete: SetNull)
1075
+ intermediate_feedback IntermediateFeedback? @relation(fields: [intermediate_feedback_id], references: [id], onDelete: SetNull)
1076
+ job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
1077
+
1078
+ @@unique([interview_id, order_no])
1079
+ @@index([interview_id])
1080
+ @@index([job_description_id])
1081
+ }
1082
+
1083
+ enum FirstLoginStatus {
1084
+ PENDING
1085
+ COMPLETED
1086
+ }
1087
+
1088
+ model User {
1089
+ id String @id @default(uuid())
1090
+ email String @unique
1091
+ password String
1092
+ role_id String
1093
+ role UserRole @relation(fields: [role_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
1094
+ // Back-relations are defined from Resume side via user_id
1095
+ google_id String? @unique
1096
+ refresh_token String?
1097
+ created_at DateTime @default(now())
1098
+ updated_at DateTime @updatedAt
1099
+ created_by String
1100
+ updated_by String
1101
+ is_active Boolean @default(true)
1102
+ is_self_registered Boolean @default(true)
1103
+ permission_id String? @unique
1104
+ permission Permission? @relation(fields: [permission_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
1105
+ organisation_id String?
1106
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
1107
+ applications Application[]
1108
+ resume Resume[]
1109
+ candidate_profile CandidateProfile?
1110
+ user_profile UserProfile?
1111
+ job_description JobDescription[]
1112
+ hiring_manager_job_descriptions JobDescription[] @relation("HiringManager")
1113
+ approvals Approval[]
1114
+ panelist Panelist?
1115
+ sent_messages Message[] @relation("Sent Messages")
1116
+ received_messages Message[] @relation("Received Messages")
1117
+ profile_created Boolean
1118
+ first_login_status FirstLoginStatus @default(PENDING)
1119
+ // Back-relations for interviews (optional but recommended for clarity)
1120
+ candidate_interviews Interview[] @relation("CandidateInterviews")
1121
+ interviewer_interviews Interview[] @relation("InterviewerInterviews")
1122
+ assessment_results Assessment[]
1123
+ candidate_assessments Assessment[] @relation("CandidateAssessments")
1124
+ reviewer_assessments Assessment[] @relation("ReviewerAssessments")
1125
+ candidateResponses CandidateQuestionResponse[]
1126
+ questions Question[]
1127
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
1128
+ actions Action[]
1129
+ calendly Calendly?
1130
+ google Google?
1131
+
1132
+ name String?
1133
+ phone String?
1134
+ description String?
1135
+ date_of_birth DateTime?
1136
+ designation String?
1137
+ location String?
1138
+ salary String?
1139
+ work_experience Json?
1140
+ education Json?
1141
+ notice_period String?
1142
+ gender String?
1143
+ ethnicity String?
1144
+ veteran_status String?
1145
+ disability_status String?
1146
+
1147
+ @@index([role_id])
1148
+ @@index([permission_id])
1149
+ @@index([organisation_id])
1150
+ }
1151
+
1152
+ model UserProfile {
1153
+ id String @id @default(uuid())
1154
+ created_at DateTime @default(now())
1155
+ updated_at DateTime @updatedAt
1156
+ name String
1157
+ phone String
1158
+ description String
1159
+ date_of_birth String
1160
+ designation String
1161
+ is_active Boolean @default(true)
1162
+ user User? @relation(fields: [user_id], references: [id])
1163
+ user_id String? @unique
1164
+
1165
+ work_experience Json?
1166
+ }