@adaptware/eagles-db 0.4.17 → 0.4.18

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.
Files changed (32) hide show
  1. package/README.md +5 -105
  2. package/client/edge.js +102 -5
  3. package/client/index-browser.js +97 -0
  4. package/client/index.d.ts +19359 -5843
  5. package/client/index.js +102 -5
  6. package/client/package.json +1 -1
  7. package/client/schema.prisma +239 -75
  8. package/client/wasm.js +97 -0
  9. package/package.json +1 -1
  10. package/prisma/.DS_Store +0 -0
  11. package/prisma/schema/applications.prisma +6 -4
  12. package/prisma/schema/assignment.prisma +6 -0
  13. package/prisma/schema/document.prisma +37 -0
  14. package/prisma/schema/interview.prisma +3 -0
  15. package/prisma/schema/jobApplicationFields.prisma +37 -0
  16. package/prisma/schema/jobApplicationResponse.prisma +33 -0
  17. package/prisma/schema/jobApplicationTemplate.prisma +30 -0
  18. package/prisma/schema/jobDescription.prisma +15 -11
  19. package/prisma/schema/migrations/20260519120000_interview_deadline/migration.sql +2 -0
  20. package/prisma/schema/migrations/20260520120000_interview_duration_drop_deadline/migration.sql +30 -0
  21. package/prisma/schema/migrations/20260602120000_resume_file_hash_drop_unique/migration.sql +2 -0
  22. package/prisma/schema/migrations/20260603120000_job_application_field_is_mandatory/migration.sql +2 -0
  23. package/prisma/schema/migrations/20260604120000_job_application_response_updated_by_organisation/migration.sql +2 -0
  24. package/prisma/schema/migrations/20260605120000_drop_document_application_id/migration.sql +3 -0
  25. package/prisma/schema/migrations/20260610120000_jaf_template_model/migration.sql +70 -0
  26. package/prisma/schema/migrations/20260610130000_assignment_document_fks/migration.sql +15 -0
  27. package/prisma/schema/migrations/20260610140000_jaf_draft_activation/migration.sql +12 -0
  28. package/prisma/schema/organisation.prisma +30 -27
  29. package/prisma/schema/resume.prisma +5 -1
  30. package/prisma/schema/user.prisma +1 -0
  31. package/prisma/schema/migrations/20260610100000_add_communication/migration.sql +0 -131
  32. package/prisma/schema/migrations/20260610170000_add_communication_application_scope/migration.sql +0 -45
@@ -0,0 +1,37 @@
1
+ model Document {
2
+ // Primary key
3
+ id String @id @default(uuid())
4
+ // Foreign keys
5
+ organisation_id String?
6
+ candidate_id String?
7
+ // Data fields
8
+ original_file_name String
9
+ stored_file_name String
10
+ file_extension String?
11
+ s3_bucket String?
12
+ s3_key String?
13
+ mime_type String?
14
+ file_size BigInt?
15
+ file_hash String?
16
+ metadata Json?
17
+ // Audit fields
18
+ created_at DateTime @default(now())
19
+ updated_at DateTime @updatedAt
20
+ created_by String
21
+ updated_by String
22
+ is_active Boolean @default(true)
23
+ // Relations
24
+ organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
25
+ candidate User? @relation(fields: [candidate_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
26
+ resume Resume?
27
+ job_description_source JobDescription?
28
+ interview_recording Interview?
29
+ job_application_responses JobApplicationResponse[]
30
+ assignment_solution Assignment? @relation("AssignmentSolutionDocument")
31
+ assignment_zip Assignment? @relation("AssignmentZipDocument")
32
+
33
+ // Indexes
34
+ @@index([candidate_id])
35
+ @@index([organisation_id, candidate_id])
36
+ @@index([file_hash])
37
+ }
@@ -45,7 +45,9 @@ model Interview {
45
45
  actual_end_time DateTime?
46
46
  /// Interview length in minutes (source of truth; not derived from schedule window).
47
47
  duration Int?
48
+ /// @deprecated Prefer `recording_document_id` + `Document` (type INTERVIEW_RECORDING).
48
49
  recording_url String?
50
+ recording_document_id String? @unique
49
51
  evaluation_type EvaluationType? @default(TREADSPACE_AI_ASSISTED)
50
52
  ai_assistance_mode AiAssistanceMode? @default(ASSISTED)
51
53
  interview_status InterviewStatus @default(SCHEDULED)
@@ -85,6 +87,7 @@ model Interview {
85
87
  candidate User? @relation("CandidateInterviews", fields: [candidate_id], references: [id], onDelete: SetNull)
86
88
  interviewer User? @relation("InterviewerInterviews", fields: [interviewer_id], references: [id], onDelete: SetNull)
87
89
  organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
90
+ recording_document Document? @relation(fields: [recording_document_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
88
91
  job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
89
92
  resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
90
93
  evaluation_plan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
@@ -0,0 +1,37 @@
1
+ enum JobApplicationFieldType {
2
+ TEXT
3
+ NUMBER
4
+ DATE
5
+ BOOLEAN
6
+ MULTI_SELECT
7
+ FILE
8
+ DROP_DOWN
9
+ }
10
+
11
+ model JobApplicationField {
12
+ /// Primary key (UUID)
13
+ id String @id @default(uuid())
14
+ /// Foreign keys
15
+ organisation_id String
16
+ template_id String
17
+ /// Data fields
18
+ field_type JobApplicationFieldType
19
+ label String
20
+ description String?
21
+ is_mandatory Boolean @default(false)
22
+ is_draft Boolean @default(true)
23
+ options String[]
24
+ /// Audit fields
25
+ is_active Boolean @default(true)
26
+ created_by String
27
+ updated_by String
28
+ created_at DateTime @default(now())
29
+ updated_at DateTime @updatedAt
30
+ /// Relations
31
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
32
+ job_application_template JobApplicationTemplate @relation(fields: [template_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
33
+ job_application_responses JobApplicationResponse[]
34
+
35
+ /// Indexes
36
+ @@index([organisation_id, template_id])
37
+ }
@@ -0,0 +1,33 @@
1
+ model JobApplicationResponse {
2
+ /// Primary key
3
+ id String @id @default(uuid())
4
+ /// Foreign keys
5
+ application_id String
6
+ job_application_field_id String?
7
+ document_id String?
8
+ /// Answer payload
9
+ response Json?
10
+ /// Denormalized question snapshot (immutable on candidate save)
11
+ field_type JobApplicationFieldType?
12
+ label String?
13
+ description String?
14
+ is_mandatory Boolean?
15
+ is_draft Boolean?
16
+ is_submitted Boolean @default(false)
17
+ options String[]
18
+ updated_by_organisation Boolean @default(false)
19
+ /// Audit fields
20
+ created_at DateTime @default(now())
21
+ updated_at DateTime @updatedAt
22
+ created_by String
23
+ updated_by String
24
+ is_active Boolean @default(true)
25
+ /// Relations
26
+ application Application @relation(fields: [application_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
27
+ field JobApplicationField? @relation(fields: [job_application_field_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
28
+ document Document? @relation(fields: [document_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
29
+
30
+ /// Partial unique on (application_id, job_application_field_id) WHERE job_application_field_id IS NOT NULL — see migration SQL
31
+ @@index([application_id])
32
+ @@index([job_application_field_id])
33
+ }
@@ -0,0 +1,30 @@
1
+ enum JobApplicationTemplateScope {
2
+ ORGANIZATION
3
+ JOB
4
+ }
5
+
6
+ model JobApplicationTemplate {
7
+ /// Primary key
8
+ id String @id @default(uuid())
9
+ /// Foreign keys
10
+ organisation_id String
11
+ job_description_id String? @unique
12
+ /// Data fields
13
+ name String
14
+ description String?
15
+ scope JobApplicationTemplateScope @default(ORGANIZATION)
16
+ /// Audit fields
17
+ is_active Boolean @default(true)
18
+ created_by String
19
+ updated_by String
20
+ created_at DateTime @default(now())
21
+ updated_at DateTime @updatedAt
22
+ /// Relations
23
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
24
+ job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
25
+ fields JobApplicationField[]
26
+
27
+ /// Indexes
28
+ @@index([organisation_id, scope])
29
+ @@index([job_description_id])
30
+ }
@@ -7,28 +7,31 @@ enum JobDescriptionStatus {
7
7
  }
8
8
 
9
9
  model JobDescription {
10
- id String @id @default(uuid())
10
+ id String @id @default(uuid())
11
11
  organisation_id String
12
12
  hiring_manager_id String?
13
- status JobDescriptionStatus @default(DRAFT)
13
+ status JobDescriptionStatus @default(DRAFT)
14
14
  screeningQuestions String[]
15
15
  recommendedQuestions Json[]
16
+ /// @deprecated Prefer `source_document_id` + `Document` (type JOB_DESCRIPTION).
16
17
  uploaded_job_description_path String?
17
- is_plan_published Boolean @default(false)
18
- is_posted Boolean @default(false)
18
+ source_document_id String? @unique
19
+ is_plan_published Boolean @default(false)
20
+ is_posted Boolean @default(false)
19
21
  summary Json?
20
22
  ai_insight Json?
21
23
  job_fit_comparison Json?
22
24
  // Audit fields
23
- created_at DateTime @default(now())
24
- updated_at DateTime @updatedAt
25
+ created_at DateTime @default(now())
26
+ updated_at DateTime @updatedAt
25
27
  created_by String
26
28
  updated_by String
27
- is_active Boolean @default(true)
28
- openings Int @default(1)
29
+ is_active Boolean @default(true)
30
+ openings Int @default(1)
29
31
  job_profile_id String?
30
- job_profile JobProfile? @relation(fields: [job_profile_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
31
- organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
32
+ job_profile JobProfile? @relation(fields: [job_profile_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
33
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
34
+ source_document Document? @relation(fields: [source_document_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
32
35
  applications Application[]
33
36
  interviews Interview[]
34
37
  assignments Assignment[]
@@ -40,10 +43,11 @@ model JobDescription {
40
43
  approvals Approval[] // one-to-many relation
41
44
  resumes Resume[] // one-to-many link
42
45
  budget Budget?
43
- hiring_manager User? @relation("HiringManager", fields: [hiring_manager_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
46
+ hiring_manager User? @relation("HiringManager", fields: [hiring_manager_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
44
47
  recruiters User[]
45
48
  transcripts Transcript[]
46
49
  integration_job_syncs IntegrationJobSync[]
50
+ job_application_template JobApplicationTemplate?
47
51
  conversations Conversation[]
48
52
  communication_messages CommunicationMessage[]
49
53
 
@@ -0,0 +1,2 @@
1
+ -- Full AI interview completion window (calendar days); nullable for non–Full AI rows.
2
+ ALTER TABLE "Interview" ADD COLUMN IF NOT EXISTS "deadline" INTEGER;
@@ -0,0 +1,30 @@
1
+ -- Interview.duration (minutes) replaces timestamp-derived length; Interview.deadline removed (window = scheduled_end_time).
2
+ ALTER TABLE "Interview" ADD COLUMN IF NOT EXISTS "duration" INTEGER;
3
+
4
+ ALTER TABLE "Interview" DROP COLUMN IF EXISTS "deadline";
5
+
6
+ -- Best-effort inline backfill (Full AI rows may be wrong until backfill-interview-duration.ts runs).
7
+ UPDATE "Interview" i
8
+ SET "duration" = GREATEST(
9
+ 1,
10
+ ROUND(
11
+ EXTRACT(EPOCH FROM (i."scheduled_end_time" - i."scheduled_start_time")) / 60
12
+ )::integer
13
+ )
14
+ WHERE i."duration" IS NULL
15
+ AND i."scheduled_start_time" IS NOT NULL
16
+ AND i."scheduled_end_time" IS NOT NULL
17
+ AND i."scheduled_end_time" > i."scheduled_start_time"
18
+ AND (i."evaluation_type" IS NULL OR i."evaluation_type"::text <> 'TREADSPACE_FULL_AI');
19
+
20
+ UPDATE "Interview" i
21
+ SET "duration" = oe."duration"
22
+ FROM "OngoingEvaluation" oe
23
+ WHERE oe."interview_id" = i."id"
24
+ AND i."duration" IS NULL
25
+ AND oe."duration" IS NOT NULL
26
+ AND oe."duration_unit" = 'MINUTES';
27
+
28
+ UPDATE "Interview"
29
+ SET "duration" = 45
30
+ WHERE "duration" IS NULL;
@@ -0,0 +1,2 @@
1
+ -- Drop unique constraint on Resume.file_hash (dedup moves to Document.file_hash).
2
+ DROP INDEX IF EXISTS "Resume_file_hash_key";
@@ -0,0 +1,2 @@
1
+ -- Add is_mandatory flag to job application form fields.
2
+ ALTER TABLE "JobApplicationField" ADD COLUMN IF NOT EXISTS "is_mandatory" BOOLEAN NOT NULL DEFAULT false;
@@ -0,0 +1,2 @@
1
+ -- Track whether the latest response change was made by the organisation (vs candidate).
2
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "updated_by_organisation" BOOLEAN NOT NULL DEFAULT false;
@@ -0,0 +1,3 @@
1
+ -- Drop Document.application_id FK and column (linking stays on JobApplicationResponse.document_id).
2
+ ALTER TABLE "Document" DROP CONSTRAINT IF EXISTS "Document_application_id_fkey";
3
+ ALTER TABLE "Document" DROP COLUMN IF EXISTS "application_id";
@@ -0,0 +1,70 @@
1
+ -- CreateEnum
2
+ CREATE TYPE "JobApplicationTemplateScope" AS ENUM ('ORGANIZATION', 'JOB');
3
+
4
+ -- CreateTable
5
+ CREATE TABLE "JobApplicationTemplate" (
6
+ "id" TEXT NOT NULL,
7
+ "organisation_id" TEXT NOT NULL,
8
+ "job_description_id" TEXT,
9
+ "name" TEXT NOT NULL,
10
+ "description" TEXT,
11
+ "scope" "JobApplicationTemplateScope" NOT NULL DEFAULT 'ORGANIZATION',
12
+ "is_active" BOOLEAN NOT NULL DEFAULT true,
13
+ "created_by" TEXT NOT NULL,
14
+ "updated_by" TEXT NOT NULL,
15
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
16
+ "updated_at" TIMESTAMP(3) NOT NULL,
17
+
18
+ CONSTRAINT "JobApplicationTemplate_pkey" PRIMARY KEY ("id")
19
+ );
20
+
21
+ -- Drop legacy scope model on JobApplicationField (greenfield — no data backfill)
22
+ ALTER TABLE "JobApplicationField" DROP CONSTRAINT IF EXISTS "JobApplicationField_job_description_id_fkey";
23
+ ALTER TABLE "JobApplicationField" DROP CONSTRAINT IF EXISTS "JobApplicationField_application_id_fkey";
24
+ DROP INDEX IF EXISTS "JobApplicationField_organisation_id_scope_idx";
25
+ DROP INDEX IF EXISTS "JobApplicationField_job_description_id_idx";
26
+ DROP INDEX IF EXISTS "JobApplicationField_application_id_idx";
27
+
28
+ ALTER TABLE "JobApplicationField" DROP COLUMN IF EXISTS "scope";
29
+ ALTER TABLE "JobApplicationField" DROP COLUMN IF EXISTS "job_description_id";
30
+ ALTER TABLE "JobApplicationField" DROP COLUMN IF EXISTS "application_id";
31
+
32
+ DROP TYPE IF EXISTS "JobApplicationFieldScope";
33
+
34
+ ALTER TABLE "JobApplicationField" ADD COLUMN IF NOT EXISTS "template_id" TEXT;
35
+
36
+ -- JobApplicationResponse snapshot columns
37
+ ALTER TABLE "JobApplicationResponse" DROP CONSTRAINT IF EXISTS "JobApplicationResponse_job_application_field_id_fkey";
38
+ DROP INDEX IF EXISTS "JobApplicationResponse_application_id_job_application_field_id_key";
39
+
40
+ ALTER TABLE "JobApplicationResponse" ALTER COLUMN "job_application_field_id" DROP NOT NULL;
41
+
42
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "field_type" "JobApplicationFieldType";
43
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "label" TEXT;
44
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "description" TEXT;
45
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "is_mandatory" BOOLEAN;
46
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "options" TEXT[] DEFAULT ARRAY[]::TEXT[];
47
+
48
+ -- Document: remove application link
49
+ ALTER TABLE "Document" DROP CONSTRAINT IF EXISTS "Document_application_id_fkey";
50
+ DROP INDEX IF EXISTS "Document_application_id_idx";
51
+ ALTER TABLE "Document" DROP COLUMN IF EXISTS "application_id";
52
+
53
+ -- Greenfield: no legacy JAF rows — clear any orphan fields before NOT NULL
54
+ DELETE FROM "JobApplicationField";
55
+ ALTER TABLE "JobApplicationField" ALTER COLUMN "template_id" SET NOT NULL;
56
+
57
+ -- Indexes and foreign keys
58
+ CREATE UNIQUE INDEX IF NOT EXISTS "JobApplicationTemplate_job_description_id_key" ON "JobApplicationTemplate"("job_description_id");
59
+ CREATE INDEX IF NOT EXISTS "JobApplicationTemplate_organisation_id_scope_idx" ON "JobApplicationTemplate"("organisation_id", "scope");
60
+ CREATE INDEX IF NOT EXISTS "JobApplicationTemplate_job_description_id_idx" ON "JobApplicationTemplate"("job_description_id");
61
+
62
+ ALTER TABLE "JobApplicationTemplate" ADD CONSTRAINT "JobApplicationTemplate_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
63
+ ALTER TABLE "JobApplicationTemplate" ADD CONSTRAINT "JobApplicationTemplate_job_description_id_fkey" FOREIGN KEY ("job_description_id") REFERENCES "JobDescription"("id") ON DELETE CASCADE ON UPDATE CASCADE;
64
+
65
+ ALTER TABLE "JobApplicationField" ADD CONSTRAINT "JobApplicationField_template_id_fkey" FOREIGN KEY ("template_id") REFERENCES "JobApplicationTemplate"("id") ON DELETE CASCADE ON UPDATE CASCADE;
66
+ CREATE INDEX IF NOT EXISTS "JobApplicationField_organisation_id_template_id_idx" ON "JobApplicationField"("organisation_id", "template_id");
67
+
68
+ ALTER TABLE "JobApplicationResponse" ADD CONSTRAINT "JobApplicationResponse_job_application_field_id_fkey" FOREIGN KEY ("job_application_field_id") REFERENCES "JobApplicationField"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
69
+
70
+ CREATE UNIQUE INDEX "JobApplicationResponse_application_id_job_application_field_id_key" ON "JobApplicationResponse"("application_id", "job_application_field_id") WHERE "job_application_field_id" IS NOT NULL;
@@ -0,0 +1,15 @@
1
+ -- AlterTable
2
+ ALTER TABLE "Assignment" ADD COLUMN "solution_document_id" TEXT,
3
+ ADD COLUMN "zip_document_id" TEXT;
4
+
5
+ -- CreateIndex
6
+ CREATE UNIQUE INDEX "Assignment_solution_document_id_key" ON "Assignment"("solution_document_id");
7
+
8
+ -- CreateIndex
9
+ CREATE UNIQUE INDEX "Assignment_zip_document_id_key" ON "Assignment"("zip_document_id");
10
+
11
+ -- AddForeignKey
12
+ ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_solution_document_id_fkey" FOREIGN KEY ("solution_document_id") REFERENCES "Document"("id") ON DELETE SET NULL ON UPDATE CASCADE;
13
+
14
+ -- AddForeignKey
15
+ ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_zip_document_id_fkey" FOREIGN KEY ("zip_document_id") REFERENCES "Document"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,12 @@
1
+ -- JobApplicationField: draft gate for template/job fields
2
+ ALTER TABLE "JobApplicationField" ADD COLUMN IF NOT EXISTS "is_draft" BOOLEAN DEFAULT true;
3
+ UPDATE "JobApplicationField" SET "is_draft" = false WHERE "is_draft" IS NULL;
4
+ ALTER TABLE "JobApplicationField" ALTER COLUMN "is_draft" SET NOT NULL;
5
+ ALTER TABLE "JobApplicationField" ALTER COLUMN "is_draft" SET DEFAULT true;
6
+
7
+ -- JobApplicationResponse: per-row draft/submit state
8
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "is_draft" BOOLEAN;
9
+ ALTER TABLE "JobApplicationResponse" ADD COLUMN IF NOT EXISTS "is_submitted" BOOLEAN DEFAULT false;
10
+ UPDATE "JobApplicationResponse" SET "is_draft" = false WHERE "is_draft" IS NULL;
11
+ UPDATE "JobApplicationResponse" SET "is_submitted" = false WHERE "is_submitted" IS NULL;
12
+ ALTER TABLE "JobApplicationResponse" ALTER COLUMN "is_draft" SET DEFAULT false;
@@ -18,33 +18,36 @@ model Organisation {
18
18
  company_values Json[]
19
19
  allowed_email_domains String[]
20
20
 
21
- interviewers User[]
22
- created_at DateTime @default(now())
23
- updated_at DateTime @updatedAt
24
- created_by String
25
- updated_by String
26
- is_active Boolean @default(true)
27
- alias String? @unique
28
- logo String?
29
- applications Application[]
30
- user_roles UserRole[]
31
- job_descriptions JobDescription[]
32
- job_profiles JobProfile[]
33
- assessment_library AssessmentLibrary[]
34
- assignment_library AssignmentLibrary[]
35
- interviews Interview[]
36
- assignments Assignment[]
37
- fit_check FitCheck[] // one-to-many link
38
- resumes Resume[] // one-to-many link
39
- approvals Approval[] // one-to-many link
40
- suggestions Suggestion[]
41
- ongoing_evaluations OngoingEvaluation[] // optional one-to-many
42
- actions Action[]
43
- integration_credentials IntegrationCredential[]
44
- zoho_sync_mappings ZohoSyncMapping[]
45
- assessments Assessment[]
46
- timezone String @default("Asia/Kolkata")
47
- organisation_configs OrganisationConfig[]
21
+ interviewers User[]
22
+ created_at DateTime @default(now())
23
+ updated_at DateTime @updatedAt
24
+ created_by String
25
+ updated_by String
26
+ is_active Boolean @default(true)
27
+ alias String? @unique
28
+ logo String?
29
+ applications Application[]
30
+ user_roles UserRole[]
31
+ job_descriptions JobDescription[]
32
+ job_profiles JobProfile[]
33
+ assessment_library AssessmentLibrary[]
34
+ assignment_library AssignmentLibrary[]
35
+ interviews Interview[]
36
+ assignments Assignment[]
37
+ fit_check FitCheck[] // one-to-many link
38
+ resumes Resume[] // one-to-many link
39
+ approvals Approval[] // one-to-many link
40
+ suggestions Suggestion[]
41
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
42
+ actions Action[]
43
+ integration_credentials IntegrationCredential[]
44
+ zoho_sync_mappings ZohoSyncMapping[]
45
+ assessments Assessment[]
46
+ timezone String @default("Asia/Kolkata")
47
+ organisation_configs OrganisationConfig[]
48
+ job_application_fields JobApplicationField[]
49
+ documents Document[]
50
+ job_application_templates JobApplicationTemplate[]
48
51
 
49
52
  channel_provider_configs ChannelProviderConfig[]
50
53
  conversations Conversation[]
@@ -3,8 +3,11 @@ model Resume {
3
3
  user_id String?
4
4
  organisation_id String?
5
5
  job_description_id String?
6
+ /// @deprecated Prefer `document_id` + `Document`. Kept until backfill completes.
6
7
  uploaded_resume_path String?
7
- file_hash String? @unique
8
+ document_id String? @unique
9
+ /// @deprecated Prefer `Document.file_hash`. Kept for legacy read fallback.
10
+ file_hash String?
8
11
  summary Json?
9
12
  created_at DateTime @default(now())
10
13
  updated_at DateTime @updatedAt
@@ -15,6 +18,7 @@ model Resume {
15
18
  user User? @relation(fields: [user_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
16
19
  organisation Organisation? @relation(fields: [organisation_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
17
20
  job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
21
+ document Document? @relation(fields: [document_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
18
22
  applications Application[]
19
23
  interviews Interview[]
20
24
  ongoing_evaluations OngoingEvaluation[] // optional one-to-many
@@ -85,6 +85,7 @@ model User {
85
85
  veteran_status String?
86
86
  disability_status String?
87
87
  professional_expertise String?
88
+ documents Document[]
88
89
 
89
90
  @@index([role_id])
90
91
  @@index([permission_id])
@@ -1,131 +0,0 @@
1
- -- CreateEnum
2
- CREATE TYPE "CommChannel" AS ENUM ('WHATSAPP', 'EMAIL', 'SMS', 'CALL');
3
-
4
- -- CreateEnum
5
- CREATE TYPE "CommProvider" AS ENUM ('META_WHATSAPP', 'TWILIO', 'GUPSHUP', 'MTALKZ', 'THREE_SIXTY_DIALOG', 'GMAIL', 'OUTLOOK', 'GENERIC_SMTP', 'GENERIC');
6
-
7
- -- CreateEnum
8
- CREATE TYPE "CommDirection" AS ENUM ('INBOUND', 'OUTBOUND');
9
-
10
- -- CreateEnum
11
- CREATE TYPE "CommMessageStatus" AS ENUM ('QUEUED', 'SENT', 'DELIVERED', 'READ', 'FAILED', 'RECEIVED');
12
-
13
- -- CreateTable
14
- CREATE TABLE "ChannelProviderConfig" (
15
- "id" TEXT NOT NULL,
16
- "organisation_id" TEXT NOT NULL,
17
- "channel" "CommChannel" NOT NULL,
18
- "provider" "CommProvider" NOT NULL,
19
- "credentials" TEXT,
20
- "metadata" JSONB NOT NULL DEFAULT '{}',
21
- "is_active" BOOLEAN NOT NULL DEFAULT true,
22
- "is_default" BOOLEAN NOT NULL DEFAULT true,
23
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
24
- "updated_at" TIMESTAMP(3) NOT NULL,
25
- "created_by" TEXT NOT NULL,
26
- "updated_by" TEXT NOT NULL,
27
-
28
- CONSTRAINT "ChannelProviderConfig_pkey" PRIMARY KEY ("id")
29
- );
30
-
31
- -- CreateTable
32
- CREATE TABLE "Conversation" (
33
- "id" TEXT NOT NULL,
34
- "organisation_id" TEXT NOT NULL,
35
- "channel" "CommChannel" NOT NULL,
36
- "provider" "CommProvider" NOT NULL,
37
- "channel_provider_id" TEXT,
38
- "external_id" TEXT NOT NULL,
39
- "contact_user_id" TEXT,
40
- "provider_thread_id" TEXT,
41
- "subject" TEXT,
42
- "status" TEXT NOT NULL DEFAULT 'open',
43
- "unread_count" INTEGER NOT NULL DEFAULT 0,
44
- "last_message_at" TIMESTAMP(3),
45
- "metadata" JSONB NOT NULL DEFAULT '{}',
46
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
47
- "updated_at" TIMESTAMP(3) NOT NULL,
48
- "created_by" TEXT NOT NULL,
49
- "updated_by" TEXT NOT NULL,
50
-
51
- CONSTRAINT "Conversation_pkey" PRIMARY KEY ("id")
52
- );
53
-
54
- -- CreateTable
55
- CREATE TABLE "CommunicationMessage" (
56
- "id" TEXT NOT NULL,
57
- "conversation_id" TEXT NOT NULL,
58
- "organisation_id" TEXT NOT NULL,
59
- "channel" "CommChannel" NOT NULL,
60
- "provider" "CommProvider" NOT NULL,
61
- "channel_provider_id" TEXT,
62
- "direction" "CommDirection" NOT NULL,
63
- "status" "CommMessageStatus" NOT NULL,
64
- "body" TEXT,
65
- "from_identifier" TEXT NOT NULL,
66
- "to_identifier" TEXT NOT NULL,
67
- "sender_user_id" TEXT,
68
- "provider_message_id" TEXT,
69
- "template_name" TEXT,
70
- "attachments" JSONB NOT NULL DEFAULT '[]',
71
- "metadata" JSONB NOT NULL DEFAULT '{}',
72
- "error" TEXT,
73
- "sent_at" TIMESTAMP(3),
74
- "delivered_at" TIMESTAMP(3),
75
- "read_at" TIMESTAMP(3),
76
- "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
77
- "updated_at" TIMESTAMP(3) NOT NULL,
78
-
79
- CONSTRAINT "CommunicationMessage_pkey" PRIMARY KEY ("id")
80
- );
81
-
82
- -- CreateIndex
83
- CREATE UNIQUE INDEX "ChannelProviderConfig_organisation_id_channel_provider_key" ON "ChannelProviderConfig"("organisation_id", "channel", "provider");
84
-
85
- -- CreateIndex
86
- CREATE INDEX "ChannelProviderConfig_organisation_id_channel_idx" ON "ChannelProviderConfig"("organisation_id", "channel");
87
-
88
- -- CreateIndex
89
- CREATE INDEX "ChannelProviderConfig_organisation_id_channel_is_active_idx" ON "ChannelProviderConfig"("organisation_id", "channel", "is_active");
90
-
91
- -- CreateIndex
92
- CREATE UNIQUE INDEX "Conversation_organisation_id_channel_provider_external_id_key" ON "Conversation"("organisation_id", "channel", "provider", "external_id");
93
-
94
- -- CreateIndex
95
- CREATE INDEX "Conversation_organisation_id_channel_idx" ON "Conversation"("organisation_id", "channel");
96
-
97
- -- CreateIndex
98
- CREATE INDEX "Conversation_organisation_id_last_message_at_idx" ON "Conversation"("organisation_id", "last_message_at");
99
-
100
- -- CreateIndex
101
- CREATE INDEX "Conversation_external_id_idx" ON "Conversation"("external_id");
102
-
103
- -- CreateIndex
104
- CREATE UNIQUE INDEX "CommunicationMessage_provider_provider_message_id_key" ON "CommunicationMessage"("provider", "provider_message_id");
105
-
106
- -- CreateIndex
107
- CREATE INDEX "CommunicationMessage_conversation_id_created_at_idx" ON "CommunicationMessage"("conversation_id", "created_at");
108
-
109
- -- CreateIndex
110
- CREATE INDEX "CommunicationMessage_organisation_id_channel_created_at_idx" ON "CommunicationMessage"("organisation_id", "channel", "created_at");
111
-
112
- -- CreateIndex
113
- CREATE INDEX "CommunicationMessage_organisation_id_status_idx" ON "CommunicationMessage"("organisation_id", "status");
114
-
115
- -- AddForeignKey
116
- ALTER TABLE "ChannelProviderConfig" ADD CONSTRAINT "ChannelProviderConfig_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
117
-
118
- -- AddForeignKey
119
- ALTER TABLE "Conversation" ADD CONSTRAINT "Conversation_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
120
-
121
- -- AddForeignKey
122
- ALTER TABLE "Conversation" ADD CONSTRAINT "Conversation_channel_provider_id_fkey" FOREIGN KEY ("channel_provider_id") REFERENCES "ChannelProviderConfig"("id") ON DELETE SET NULL ON UPDATE CASCADE;
123
-
124
- -- AddForeignKey
125
- ALTER TABLE "CommunicationMessage" ADD CONSTRAINT "CommunicationMessage_conversation_id_fkey" FOREIGN KEY ("conversation_id") REFERENCES "Conversation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
126
-
127
- -- AddForeignKey
128
- ALTER TABLE "CommunicationMessage" ADD CONSTRAINT "CommunicationMessage_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
129
-
130
- -- AddForeignKey
131
- ALTER TABLE "CommunicationMessage" ADD CONSTRAINT "CommunicationMessage_channel_provider_id_fkey" FOREIGN KEY ("channel_provider_id") REFERENCES "ChannelProviderConfig"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -1,45 +0,0 @@
1
- -- AlterTable: Conversation
2
- ALTER TABLE "Conversation"
3
- ADD COLUMN "application_id" TEXT,
4
- ADD COLUMN "job_description_id" TEXT;
5
-
6
- -- AlterTable: CommunicationMessage
7
- ALTER TABLE "CommunicationMessage"
8
- ADD COLUMN "application_id" TEXT,
9
- ADD COLUMN "job_description_id" TEXT;
10
-
11
- -- CreateIndex
12
- CREATE INDEX "Conversation_organisation_id_application_id_idx" ON "Conversation"("organisation_id", "application_id");
13
-
14
- -- CreateIndex
15
- CREATE INDEX "Conversation_organisation_id_job_description_id_idx" ON "Conversation"("organisation_id", "job_description_id");
16
-
17
- -- CreateIndex
18
- CREATE INDEX "CommunicationMessage_organisation_id_application_id_idx" ON "CommunicationMessage"("organisation_id", "application_id");
19
-
20
- -- CreateIndex
21
- CREATE INDEX "CommunicationMessage_organisation_id_job_description_id_idx" ON "CommunicationMessage"("organisation_id", "job_description_id");
22
-
23
- -- AddForeignKey
24
- ALTER TABLE "Conversation"
25
- ADD CONSTRAINT "Conversation_application_id_fkey"
26
- FOREIGN KEY ("application_id") REFERENCES "Application"("id")
27
- ON DELETE SET NULL ON UPDATE CASCADE;
28
-
29
- -- AddForeignKey
30
- ALTER TABLE "Conversation"
31
- ADD CONSTRAINT "Conversation_job_description_id_fkey"
32
- FOREIGN KEY ("job_description_id") REFERENCES "JobDescription"("id")
33
- ON DELETE SET NULL ON UPDATE CASCADE;
34
-
35
- -- AddForeignKey
36
- ALTER TABLE "CommunicationMessage"
37
- ADD CONSTRAINT "CommunicationMessage_application_id_fkey"
38
- FOREIGN KEY ("application_id") REFERENCES "Application"("id")
39
- ON DELETE SET NULL ON UPDATE CASCADE;
40
-
41
- -- AddForeignKey
42
- ALTER TABLE "CommunicationMessage"
43
- ADD CONSTRAINT "CommunicationMessage_job_description_id_fkey"
44
- FOREIGN KEY ("job_description_id") REFERENCES "JobDescription"("id")
45
- ON DELETE SET NULL ON UPDATE CASCADE;