@adaptware/eagles-db 0.5.20 → 0.5.22

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 (33) hide show
  1. package/client/edge.js +29 -96
  2. package/client/index-browser.js +18 -85
  3. package/client/index.d.ts +757 -5626
  4. package/client/index.js +29 -96
  5. package/client/package.json +1 -1
  6. package/client/schema.prisma +62 -156
  7. package/client/wasm.js +29 -96
  8. package/package.json +1 -1
  9. package/prisma/.DS_Store +0 -0
  10. package/prisma/schema/activityEvent.prisma +8 -4
  11. package/prisma/schema/applications.prisma +27 -3
  12. package/prisma/schema/integration.prisma +1 -0
  13. package/prisma/schema/migrations/.DS_Store +0 -0
  14. package/prisma/schema/migrations/20260610100000_add_communication/migration.sql +131 -0
  15. package/prisma/schema/migrations/20260610170000_add_communication_application_scope/migration.sql +45 -0
  16. package/prisma/schema/migrations/20260718120000_add_hiring_plan/migration.sql +208 -0
  17. package/prisma/schema/migrations/20260718140000_hiring_plan_assumptions/migration.sql +2 -0
  18. package/prisma/schema/migrations/20260807140000_simplify_offer_status_model/migration.sql +109 -0
  19. package/prisma/schema/offer.prisma +9 -132
  20. package/client/libquery_engine-darwin.dylib.node +0 -0
  21. package/prisma/migrations/20260519120000_migrate_shortlisted_to_selected/migration.sql +0 -2
  22. package/prisma/schema/.DS_Store +0 -0
  23. package/prisma/schema/migrations/20260519120000_add_analytics_schema/migration.sql +0 -84
  24. package/prisma/schema/migrations/20260625120000_add_interviewer_analytics/migration.sql +0 -26
  25. package/prisma/schema/migrations/20260629120000_add_user_lifecycle_activity_events/migration.sql +0 -13
  26. package/prisma/schema/migrations/20260629140000_drop_organisation_org_code/migration.sql +0 -2
  27. package/prisma/schema/migrations/20260629160000_employee_codes_dual_interviewer_analytics/migration.sql +0 -87
  28. package/prisma/schema/migrations/20260630120000_add_application_sources/migration.sql +0 -38
  29. package/prisma/schema/migrations/20260701120000_add_source_effectiveness_analytics/migration.sql +0 -40
  30. package/prisma/schema/migrations/20260702120000_add_analytics_daily_tables/migration.sql +0 -232
  31. package/prisma/schema/migrations/20260716120000_evaluation_category_four_values/migration.sql +0 -204
  32. package/prisma/schema/migrations/20260716130000_application_withdrawn_analytics/migration.sql +0 -31
  33. package/prisma/schema/migrations/20260804120000_contact_us_optional_website_subject/migration.sql +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptware/eagles-db",
3
- "version": "0.5.20",
3
+ "version": "0.5.22",
4
4
  "description": "A Prisma client package for Treadspace database operations",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/prisma/.DS_Store CHANGED
Binary file
@@ -44,16 +44,20 @@ enum ActivityEventType {
44
44
 
45
45
  /// Offer workflow — one semantic event per business moment.
46
46
  OFFER_CREATED
47
+ OFFER_GENERATED
47
48
  OFFER_SENT
49
+ OFFER_REVISED
50
+ OFFER_ACCEPTED
51
+ OFFER_DECLINED
52
+ OFFER_WITHDRAWN
53
+ OFFER_JOINED
54
+ OFFER_NO_SHOW
55
+ /// Legacy values kept for historic ActivityEvent rows; not emitted by current flow.
48
56
  OFFER_VIEWED
49
57
  OFFER_CHANGE_REQUESTED
50
58
  OFFER_CHANGE_UNDER_REVIEW
51
59
  OFFER_COUNTER_SENT
52
- OFFER_ACCEPTED
53
- OFFER_DECLINED
54
- OFFER_WITHDRAWN
55
60
  OFFER_EXPIRED
56
- OFFER_JOINED
57
61
  OFFER_CHANGE_REQUEST_REJECTED
58
62
  OFFER_CHANGE_REQUEST_WITHDRAWN
59
63
 
@@ -4,7 +4,7 @@ enum ApplicationStatus {
4
4
  IN_PROGRESS
5
5
  SELECTED
6
6
  OFFER
7
- HIRED
7
+ JOINED
8
8
  SHORTLISTED
9
9
  REJECTED
10
10
  ON_HOLD
@@ -13,6 +13,29 @@ enum ApplicationStatus {
13
13
  @@schema("public")
14
14
  }
15
15
 
16
+ /// Fine-grained state within ApplicationStatus.OFFER. Owned by Application —
17
+ /// Offer table holds terms/letters/audit only, no lifecycle enum of its own.
18
+ enum ApplicationOfferSubstatus {
19
+ /// Offer row created with terms, no letter generated yet.
20
+ PREPARING
21
+ /// Letter DOCX generated and downloaded — awaiting manual send outside TreadSpace.
22
+ GENERATED
23
+ /// Staff manually marked the letter as sent to the candidate.
24
+ SENT
25
+ /// Revising after SENT — current letter is superseded, no active letter until next Generate.
26
+ NEGOTIATING
27
+ /// Candidate accepted (staff-recorded, no candidate portal).
28
+ ACCEPTED
29
+ /// Candidate declined — Application.status also flips to REJECTED.
30
+ DECLINED
31
+ /// Offer withdrawn by staff — Application.status also flips to REJECTED.
32
+ WITHDRAWN
33
+ /// Candidate accepted but did not join — Application.status also flips to REJECTED.
34
+ NO_SHOW
35
+
36
+ @@schema("public")
37
+ }
38
+
16
39
  model Application {
17
40
  /// Primary key
18
41
  id String @id @default(uuid())
@@ -41,8 +64,8 @@ model Application {
41
64
  unflagged_by String?
42
65
  fit_check_status FitCheckStatus?
43
66
  status ApplicationStatus @default(PENDING)
44
- /// Mirror of Offer.status for list filters and combined status chips
45
- offer_status OfferStatus?
67
+ /// Fine-grained offer-stage state. Meaningful only when status = OFFER (or was OFFER for a terminal-substatus that flipped to REJECTED / JOINED).
68
+ offer_substatus ApplicationOfferSubstatus?
46
69
  /// Audit fields
47
70
  created_at DateTime @default(now())
48
71
  updated_at DateTime @updatedAt
@@ -76,5 +99,6 @@ model Application {
76
99
  @@index([job_description_id, is_flagged])
77
100
  @@index([organisation_id, is_active, status])
78
101
  @@index([job_description_id, is_active, status])
102
+ @@index([organisation_id, offer_substatus])
79
103
  @@schema("public")
80
104
  }
@@ -1,6 +1,7 @@
1
1
  enum IntegrationProvider {
2
2
  NAUKRI
3
3
  ZOHO_RECRUIT
4
+ ZOHO_SIGN
4
5
  LINKEDIN
5
6
  GOOGLE
6
7
  MICROSOFT
@@ -0,0 +1,131 @@
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;
@@ -0,0 +1,45 @@
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;
@@ -0,0 +1,208 @@
1
+ -- CreateEnum
2
+ CREATE TYPE "HiringPlanStatus" AS ENUM ('DRAFT', 'ACTIVE', 'CLOSED');
3
+
4
+ -- CreateEnum
5
+ CREATE TYPE "PeriodType" AS ENUM ('ANNUAL');
6
+
7
+ -- CreateEnum
8
+ CREATE TYPE "EmployeeStatus" AS ENUM ('ACTIVE', 'ATTRITION_EXPECTED', 'DEPARTED');
9
+
10
+ -- CreateEnum
11
+ CREATE TYPE "AttritionRisk" AS ENUM ('LOW', 'MEDIUM', 'HIGH');
12
+
13
+ -- CreateEnum
14
+ CREATE TYPE "ReviewRating" AS ENUM (
15
+ 'OUTSTANDING',
16
+ 'EXCEEDS_EXPECTATIONS',
17
+ 'MEETS_EXPECTATIONS',
18
+ 'NEEDS_IMPROVEMENT',
19
+ 'UNSATISFACTORY'
20
+ );
21
+
22
+ -- CreateEnum
23
+ CREATE TYPE "PlannedCandidateStatus" AS ENUM (
24
+ 'IDENTIFIED',
25
+ 'IN_PIPELINE',
26
+ 'OFFER',
27
+ 'SELECTED',
28
+ 'DECLINED'
29
+ );
30
+
31
+ -- CreateTable
32
+ CREATE TABLE "HiringPlan" (
33
+ "id" TEXT NOT NULL,
34
+ "organisation_id" TEXT NOT NULL,
35
+ "fiscal_year" INTEGER NOT NULL,
36
+ "period_type" "PeriodType" NOT NULL DEFAULT 'ANNUAL',
37
+ "currency" TEXT NOT NULL DEFAULT 'INR',
38
+ "status" "HiringPlanStatus" NOT NULL DEFAULT 'DRAFT',
39
+ "total_headcount_budget" INTEGER,
40
+ "total_cost_budget" DECIMAL(18,2),
41
+ "notes" TEXT,
42
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
43
+ "updated_at" TIMESTAMP(3) NOT NULL,
44
+ "created_by" TEXT NOT NULL,
45
+ "updated_by" TEXT NOT NULL,
46
+ "is_active" BOOLEAN NOT NULL DEFAULT true,
47
+
48
+ CONSTRAINT "HiringPlan_pkey" PRIMARY KEY ("id")
49
+ );
50
+
51
+ -- CreateTable
52
+ CREATE TABLE "HiringPlanLine" (
53
+ "id" TEXT NOT NULL,
54
+ "hiring_plan_id" TEXT NOT NULL,
55
+ "business_unit" TEXT,
56
+ "level" TEXT,
57
+ "location" TEXT,
58
+ "role" TEXT,
59
+ "planned_headcount" INTEGER NOT NULL DEFAULT 1,
60
+ "cost_per_hire" DECIMAL(18,2) NOT NULL,
61
+ "start_month" INTEGER NOT NULL DEFAULT 1,
62
+ "hire_schedule" JSONB,
63
+ "job_description_id" TEXT,
64
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
65
+ "updated_at" TIMESTAMP(3) NOT NULL,
66
+ "created_by" TEXT NOT NULL,
67
+ "updated_by" TEXT NOT NULL,
68
+ "is_active" BOOLEAN NOT NULL DEFAULT true,
69
+
70
+ CONSTRAINT "HiringPlanLine_pkey" PRIMARY KEY ("id")
71
+ );
72
+
73
+ -- CreateTable
74
+ CREATE TABLE "Employee" (
75
+ "id" TEXT NOT NULL,
76
+ "organisation_id" TEXT NOT NULL,
77
+ "employee_code" TEXT,
78
+ "name" TEXT,
79
+ "email" TEXT,
80
+ "gender" TEXT,
81
+ "business_unit" TEXT,
82
+ "level" TEXT,
83
+ "location" TEXT,
84
+ "role" TEXT,
85
+ "employment_type" "JobType",
86
+ "starting_designation" TEXT,
87
+ "current_designation" TEXT,
88
+ "start_date" TIMESTAMP(3),
89
+ "starting_salary" DECIMAL(18,2),
90
+ "current_comp" DECIMAL(18,2) NOT NULL,
91
+ "currency" TEXT NOT NULL DEFAULT 'INR',
92
+ "last_increment_date" TIMESTAMP(3),
93
+ "last_increment_amount" DECIMAL(18,2),
94
+ "last_increment_pct" DECIMAL(8,4),
95
+ "last_review_date" TIMESTAMP(3),
96
+ "last_review_rating" "ReviewRating",
97
+ "last_feedback_date" TIMESTAMP(3),
98
+ "last_feedback_summary" TEXT,
99
+ "status" "EmployeeStatus" NOT NULL DEFAULT 'ACTIVE',
100
+ "attrition_risk" "AttritionRisk",
101
+ "expected_exit_date" TIMESTAMP(3),
102
+ "backfill_plan_line_id" TEXT,
103
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
104
+ "updated_at" TIMESTAMP(3) NOT NULL,
105
+ "created_by" TEXT NOT NULL,
106
+ "updated_by" TEXT NOT NULL,
107
+ "is_active" BOOLEAN NOT NULL DEFAULT true,
108
+
109
+ CONSTRAINT "Employee_pkey" PRIMARY KEY ("id")
110
+ );
111
+
112
+ -- CreateTable
113
+ CREATE TABLE "PlannedCandidate" (
114
+ "id" TEXT NOT NULL,
115
+ "hiring_plan_line_id" TEXT NOT NULL,
116
+ "candidate_profile_id" TEXT,
117
+ "name" TEXT,
118
+ "status" "PlannedCandidateStatus" NOT NULL DEFAULT 'IDENTIFIED',
119
+ "note" TEXT,
120
+ "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
121
+ "updated_at" TIMESTAMP(3) NOT NULL,
122
+ "created_by" TEXT NOT NULL,
123
+ "updated_by" TEXT NOT NULL,
124
+ "is_active" BOOLEAN NOT NULL DEFAULT true,
125
+
126
+ CONSTRAINT "PlannedCandidate_pkey" PRIMARY KEY ("id")
127
+ );
128
+
129
+ -- AlterTable
130
+ ALTER TABLE "JobDescription" ADD COLUMN "hiring_plan_line_id" TEXT;
131
+
132
+ -- AlterTable
133
+ ALTER TABLE "Budget" ADD COLUMN "hiring_plan_line_id" TEXT;
134
+
135
+ -- CreateIndex
136
+ CREATE UNIQUE INDEX "HiringPlan_organisation_id_fiscal_year_key" ON "HiringPlan"("organisation_id", "fiscal_year");
137
+
138
+ -- CreateIndex
139
+ CREATE INDEX "HiringPlan_organisation_id_idx" ON "HiringPlan"("organisation_id");
140
+
141
+ -- CreateIndex
142
+ CREATE INDEX "HiringPlan_status_idx" ON "HiringPlan"("status");
143
+
144
+ -- CreateIndex
145
+ CREATE INDEX "HiringPlanLine_hiring_plan_id_idx" ON "HiringPlanLine"("hiring_plan_id");
146
+
147
+ -- CreateIndex
148
+ CREATE INDEX "HiringPlanLine_job_description_id_idx" ON "HiringPlanLine"("job_description_id");
149
+
150
+ -- CreateIndex
151
+ CREATE INDEX "HiringPlanLine_business_unit_level_location_role_idx" ON "HiringPlanLine"("business_unit", "level", "location", "role");
152
+
153
+ -- CreateIndex
154
+ CREATE UNIQUE INDEX "Employee_organisation_id_employee_code_key" ON "Employee"("organisation_id", "employee_code");
155
+
156
+ -- CreateIndex
157
+ CREATE INDEX "Employee_organisation_id_idx" ON "Employee"("organisation_id");
158
+
159
+ -- CreateIndex
160
+ CREATE INDEX "Employee_status_idx" ON "Employee"("status");
161
+
162
+ -- CreateIndex
163
+ CREATE INDEX "Employee_business_unit_level_location_role_idx" ON "Employee"("business_unit", "level", "location", "role");
164
+
165
+ -- CreateIndex
166
+ CREATE INDEX "Employee_backfill_plan_line_id_idx" ON "Employee"("backfill_plan_line_id");
167
+
168
+ -- CreateIndex
169
+ CREATE INDEX "PlannedCandidate_hiring_plan_line_id_idx" ON "PlannedCandidate"("hiring_plan_line_id");
170
+
171
+ -- CreateIndex
172
+ CREATE INDEX "PlannedCandidate_candidate_profile_id_idx" ON "PlannedCandidate"("candidate_profile_id");
173
+
174
+ -- CreateIndex
175
+ CREATE INDEX "PlannedCandidate_status_idx" ON "PlannedCandidate"("status");
176
+
177
+ -- CreateIndex
178
+ CREATE INDEX "JobDescription_hiring_plan_line_id_idx" ON "JobDescription"("hiring_plan_line_id");
179
+
180
+ -- CreateIndex
181
+ CREATE INDEX "Budget_hiring_plan_line_id_idx" ON "Budget"("hiring_plan_line_id");
182
+
183
+ -- AddForeignKey
184
+ ALTER TABLE "HiringPlan" ADD CONSTRAINT "HiringPlan_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
185
+
186
+ -- AddForeignKey
187
+ ALTER TABLE "HiringPlanLine" ADD CONSTRAINT "HiringPlanLine_hiring_plan_id_fkey" FOREIGN KEY ("hiring_plan_id") REFERENCES "HiringPlan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
188
+
189
+ -- AddForeignKey
190
+ ALTER TABLE "HiringPlanLine" ADD CONSTRAINT "HiringPlanLine_job_description_id_fkey" FOREIGN KEY ("job_description_id") REFERENCES "JobDescription"("id") ON DELETE SET NULL ON UPDATE CASCADE;
191
+
192
+ -- AddForeignKey
193
+ ALTER TABLE "Employee" ADD CONSTRAINT "Employee_organisation_id_fkey" FOREIGN KEY ("organisation_id") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
194
+
195
+ -- AddForeignKey
196
+ ALTER TABLE "Employee" ADD CONSTRAINT "Employee_backfill_plan_line_id_fkey" FOREIGN KEY ("backfill_plan_line_id") REFERENCES "HiringPlanLine"("id") ON DELETE SET NULL ON UPDATE CASCADE;
197
+
198
+ -- AddForeignKey
199
+ ALTER TABLE "PlannedCandidate" ADD CONSTRAINT "PlannedCandidate_hiring_plan_line_id_fkey" FOREIGN KEY ("hiring_plan_line_id") REFERENCES "HiringPlanLine"("id") ON DELETE CASCADE ON UPDATE CASCADE;
200
+
201
+ -- AddForeignKey
202
+ ALTER TABLE "PlannedCandidate" ADD CONSTRAINT "PlannedCandidate_candidate_profile_id_fkey" FOREIGN KEY ("candidate_profile_id") REFERENCES "CandidateProfile"("id") ON DELETE SET NULL ON UPDATE CASCADE;
203
+
204
+ -- AddForeignKey
205
+ ALTER TABLE "JobDescription" ADD CONSTRAINT "JobDescription_hiring_plan_line_id_fkey" FOREIGN KEY ("hiring_plan_line_id") REFERENCES "HiringPlanLine"("id") ON DELETE SET NULL ON UPDATE CASCADE;
206
+
207
+ -- AddForeignKey
208
+ ALTER TABLE "Budget" ADD CONSTRAINT "Budget_hiring_plan_line_id_fkey" FOREIGN KEY ("hiring_plan_line_id") REFERENCES "HiringPlanLine"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "HiringPlan" ADD COLUMN "assumptions" JSONB;
@@ -0,0 +1,109 @@
1
+ -- Simplify offer status model:
2
+ -- * Move lifecycle from Offer.status + Offer.substatus onto Application.offer_substatus
3
+ -- * Rename ApplicationStatus.HIRED -> JOINED
4
+ -- * Split OfferLetter.sent_at -> generated_at; Offer.sent_at now = "marked as sent"
5
+ -- * Drop OfferChangeRequest, OfferApproval and their enums
6
+ -- * Drop OfferLetterStatus.VOID (never written)
7
+
8
+ -- 1. New enum for the single Application-owned offer substatus.
9
+ CREATE TYPE "public"."ApplicationOfferSubstatus" AS ENUM (
10
+ 'PREPARING',
11
+ 'GENERATED',
12
+ 'SENT',
13
+ 'NEGOTIATING',
14
+ 'ACCEPTED',
15
+ 'DECLINED',
16
+ 'WITHDRAWN',
17
+ 'NO_SHOW'
18
+ );
19
+
20
+ -- 2. Add new column and backfill from existing Offer.status / Offer.substatus.
21
+ ALTER TABLE "public"."Application"
22
+ ADD COLUMN "offer_substatus" "public"."ApplicationOfferSubstatus";
23
+
24
+ UPDATE "public"."Application" a
25
+ SET "offer_substatus" = CASE
26
+ WHEN o."status" = 'OPEN' AND o."substatus" IN ('OFFER_CREATED', 'PENDING_APPROVAL') THEN 'PREPARING'::"public"."ApplicationOfferSubstatus"
27
+ WHEN o."status" = 'OPEN' AND o."substatus" IN ('OFFER_SENT', 'VIEWED', 'COUNTER_OFFER_SENT') THEN 'SENT'::"public"."ApplicationOfferSubstatus"
28
+ WHEN o."status" = 'OPEN' AND o."substatus" IN ('CHANGE_REQUESTED', 'CHANGE_UNDER_REVIEW') THEN 'NEGOTIATING'::"public"."ApplicationOfferSubstatus"
29
+ WHEN o."status" = 'OPEN' THEN 'PREPARING'::"public"."ApplicationOfferSubstatus"
30
+ WHEN o."status" = 'ACCEPTED' THEN 'ACCEPTED'::"public"."ApplicationOfferSubstatus"
31
+ WHEN o."status" = 'JOINED' THEN 'ACCEPTED'::"public"."ApplicationOfferSubstatus"
32
+ WHEN o."status" = 'DECLINED' THEN 'DECLINED'::"public"."ApplicationOfferSubstatus"
33
+ WHEN o."status" IN ('WITHDRAWN', 'EXPIRED') THEN 'WITHDRAWN'::"public"."ApplicationOfferSubstatus"
34
+ WHEN o."status" = 'NO_SHOW' THEN 'NO_SHOW'::"public"."ApplicationOfferSubstatus"
35
+ END
36
+ FROM "public"."Offer" o
37
+ WHERE o."application_id" = a."id";
38
+
39
+ -- 3. Rename ApplicationStatus.HIRED -> JOINED (safe: all usages are offer-related).
40
+ ALTER TYPE "public"."ApplicationStatus" RENAME VALUE 'HIRED' TO 'JOINED';
41
+
42
+ -- 4. Terminal offer outcomes flip Application.status to REJECTED.
43
+ UPDATE "public"."Application"
44
+ SET "status" = 'REJECTED'
45
+ WHERE "offer_substatus" IN ('DECLINED', 'WITHDRAWN', 'NO_SHOW')
46
+ AND "status" = 'OFFER';
47
+
48
+ -- 5. Applications that were HIRED (now JOINED) with an ACCEPTED offer stay JOINED.
49
+ -- Migration above already handled ApplicationStatus rename in place.
50
+
51
+ -- 6. Drop legacy Application.offer_status mirror column and its dependent index (if any).
52
+ ALTER TABLE "public"."Application" DROP COLUMN IF EXISTS "offer_status";
53
+
54
+ -- 7. New indexes on Application.offer_substatus for pipeline filtering.
55
+ CREATE INDEX "Application_organisation_id_offer_substatus_idx"
56
+ ON "public"."Application" ("organisation_id", "offer_substatus");
57
+
58
+ -- 8. Drop Offer.status / Offer.substatus and dependent indexes.
59
+ DROP INDEX IF EXISTS "public"."Offer_organisation_id_status_idx";
60
+ DROP INDEX IF EXISTS "public"."Offer_organisation_id_substatus_idx";
61
+ DROP INDEX IF EXISTS "public"."Offer_status_idx";
62
+ DROP INDEX IF EXISTS "public"."Offer_substatus_idx";
63
+ DROP INDEX IF EXISTS "public"."Offer_expires_at_idx";
64
+
65
+ ALTER TABLE "public"."Offer"
66
+ DROP COLUMN IF EXISTS "status",
67
+ DROP COLUMN IF EXISTS "substatus",
68
+ DROP COLUMN IF EXISTS "change_request_count",
69
+ DROP COLUMN IF EXISTS "expires_at",
70
+ DROP COLUMN IF EXISTS "expired_at";
71
+
72
+ -- 9. Rename OfferLetter.sent_at -> generated_at (semantic fix: it was really "issued").
73
+ ALTER TABLE "public"."OfferLetter" RENAME COLUMN "sent_at" TO "generated_at";
74
+
75
+ -- 9a. Drop OfferLetter.viewed_at (candidate-portal artefact) and rename change_request_note.
76
+ ALTER TABLE "public"."OfferLetter" DROP COLUMN IF EXISTS "viewed_at";
77
+ ALTER TABLE "public"."OfferLetter" RENAME COLUMN "change_request_note" TO "generation_note";
78
+
79
+ -- 10. Drop change-request and approval tables (workflow removed entirely).
80
+ DROP TABLE IF EXISTS "public"."OfferChangeRequest";
81
+ DROP TABLE IF EXISTS "public"."OfferApproval";
82
+
83
+ -- 11. Drop old enums no longer referenced.
84
+ DROP TYPE IF EXISTS "public"."OfferStatus";
85
+ DROP TYPE IF EXISTS "public"."OfferSubstatus";
86
+ DROP TYPE IF EXISTS "public"."OfferChangeRequestStatus";
87
+ DROP TYPE IF EXISTS "public"."OfferChangeCategory";
88
+ DROP TYPE IF EXISTS "public"."OfferApprovalStatus";
89
+
90
+ -- 12a. Add new ActivityEventType values for the new offer flow.
91
+ ALTER TYPE "public"."ActivityEventType" ADD VALUE IF NOT EXISTS 'OFFER_GENERATED';
92
+ ALTER TYPE "public"."ActivityEventType" ADD VALUE IF NOT EXISTS 'OFFER_REVISED';
93
+ ALTER TYPE "public"."ActivityEventType" ADD VALUE IF NOT EXISTS 'OFFER_NO_SHOW';
94
+
95
+ -- 12b. Add ZOHO_SIGN to IntegrationProvider (referenced by ZohoSignService).
96
+ ALTER TYPE "public"."IntegrationProvider" ADD VALUE IF NOT EXISTS 'ZOHO_SIGN';
97
+
98
+ -- 12. OfferLetterStatus.VOID is never written; remove by rebuilding the enum with only ACTIVE + SUPERSEDED.
99
+ ALTER TYPE "public"."OfferLetterStatus" RENAME TO "OfferLetterStatus_old";
100
+ CREATE TYPE "public"."OfferLetterStatus" AS ENUM ('ACTIVE', 'SUPERSEDED');
101
+ ALTER TABLE "public"."OfferLetter"
102
+ ALTER COLUMN "status" DROP DEFAULT,
103
+ ALTER COLUMN "status" TYPE "public"."OfferLetterStatus"
104
+ USING CASE
105
+ WHEN "status"::text = 'VOID' THEN 'SUPERSEDED'::"public"."OfferLetterStatus"
106
+ ELSE "status"::text::"public"."OfferLetterStatus"
107
+ END,
108
+ ALTER COLUMN "status" SET DEFAULT 'ACTIVE';
109
+ DROP TYPE "public"."OfferLetterStatus_old";