@kernhq/module-hr 0.10.2 → 0.10.3

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.
@@ -13,7 +13,7 @@ CREATE EXTENSION IF NOT EXISTS btree_gist;
13
13
  --> statement-breakpoint
14
14
  CREATE SCHEMA IF NOT EXISTS "mod_hr";
15
15
  --> statement-breakpoint
16
- CREATE TABLE "mod_hr"."calendar_days" (
16
+ CREATE TABLE IF NOT EXISTS "mod_hr"."calendar_days" (
17
17
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
18
18
  "workspace_id" uuid NOT NULL,
19
19
  "calendar_id" uuid NOT NULL,
@@ -27,7 +27,7 @@ CREATE TABLE "mod_hr"."calendar_days" (
27
27
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
28
28
  );
29
29
  --> statement-breakpoint
30
- CREATE TABLE "mod_hr"."calendars" (
30
+ CREATE TABLE IF NOT EXISTS "mod_hr"."calendars" (
31
31
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
32
32
  "workspace_id" uuid NOT NULL,
33
33
  "name" text NOT NULL,
@@ -43,7 +43,7 @@ CREATE TABLE "mod_hr"."calendars" (
43
43
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
44
44
  );
45
45
  --> statement-breakpoint
46
- CREATE TABLE "mod_hr"."cost_centers" (
46
+ CREATE TABLE IF NOT EXISTS "mod_hr"."cost_centers" (
47
47
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
48
48
  "workspace_id" uuid NOT NULL,
49
49
  "code" text NOT NULL,
@@ -55,7 +55,7 @@ CREATE TABLE "mod_hr"."cost_centers" (
55
55
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
56
56
  );
57
57
  --> statement-breakpoint
58
- CREATE TABLE "mod_hr"."custom_field_defs" (
58
+ CREATE TABLE IF NOT EXISTS "mod_hr"."custom_field_defs" (
59
59
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
60
60
  "workspace_id" uuid NOT NULL,
61
61
  "key" text NOT NULL,
@@ -70,7 +70,7 @@ CREATE TABLE "mod_hr"."custom_field_defs" (
70
70
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
71
71
  );
72
72
  --> statement-breakpoint
73
- CREATE TABLE "mod_hr"."employments" (
73
+ CREATE TABLE IF NOT EXISTS "mod_hr"."employments" (
74
74
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
75
75
  "workspace_id" uuid NOT NULL,
76
76
  "person_id" uuid NOT NULL,
@@ -88,7 +88,7 @@ CREATE TABLE "mod_hr"."employments" (
88
88
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
89
89
  );
90
90
  --> statement-breakpoint
91
- CREATE TABLE "mod_hr"."legal_entities" (
91
+ CREATE TABLE IF NOT EXISTS "mod_hr"."legal_entities" (
92
92
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
93
93
  "workspace_id" uuid NOT NULL,
94
94
  "name" text NOT NULL,
@@ -101,7 +101,7 @@ CREATE TABLE "mod_hr"."legal_entities" (
101
101
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
102
102
  );
103
103
  --> statement-breakpoint
104
- CREATE TABLE "mod_hr"."office_assignments" (
104
+ CREATE TABLE IF NOT EXISTS "mod_hr"."office_assignments" (
105
105
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
106
106
  "workspace_id" uuid NOT NULL,
107
107
  "person_id" uuid NOT NULL,
@@ -113,7 +113,7 @@ CREATE TABLE "mod_hr"."office_assignments" (
113
113
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
114
114
  );
115
115
  --> statement-breakpoint
116
- CREATE TABLE "mod_hr"."offices" (
116
+ CREATE TABLE IF NOT EXISTS "mod_hr"."offices" (
117
117
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
118
118
  "workspace_id" uuid NOT NULL,
119
119
  "name" text NOT NULL,
@@ -134,7 +134,7 @@ CREATE TABLE "mod_hr"."offices" (
134
134
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
135
135
  );
136
136
  --> statement-breakpoint
137
- CREATE TABLE "mod_hr"."org_units" (
137
+ CREATE TABLE IF NOT EXISTS "mod_hr"."org_units" (
138
138
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
139
139
  "workspace_id" uuid NOT NULL,
140
140
  "parent_id" uuid,
@@ -147,7 +147,7 @@ CREATE TABLE "mod_hr"."org_units" (
147
147
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
148
148
  );
149
149
  --> statement-breakpoint
150
- CREATE TABLE "mod_hr"."people" (
150
+ CREATE TABLE IF NOT EXISTS "mod_hr"."people" (
151
151
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
152
152
  "workspace_id" uuid NOT NULL,
153
153
  "user_id" uuid,
@@ -166,7 +166,7 @@ CREATE TABLE "mod_hr"."people" (
166
166
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
167
167
  );
168
168
  --> statement-breakpoint
169
- CREATE TABLE "mod_hr"."people_sensitive" (
169
+ CREATE TABLE IF NOT EXISTS "mod_hr"."people_sensitive" (
170
170
  "person_id" uuid PRIMARY KEY NOT NULL,
171
171
  "workspace_id" uuid NOT NULL,
172
172
  "national_id_enc" text,
@@ -176,7 +176,7 @@ CREATE TABLE "mod_hr"."people_sensitive" (
176
176
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
177
177
  );
178
178
  --> statement-breakpoint
179
- CREATE TABLE "mod_hr"."person_documents" (
179
+ CREATE TABLE IF NOT EXISTS "mod_hr"."person_documents" (
180
180
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
181
181
  "workspace_id" uuid NOT NULL,
182
182
  "person_id" uuid NOT NULL,
@@ -189,7 +189,7 @@ CREATE TABLE "mod_hr"."person_documents" (
189
189
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
190
190
  );
191
191
  --> statement-breakpoint
192
- CREATE TABLE "mod_hr"."person_history" (
192
+ CREATE TABLE IF NOT EXISTS "mod_hr"."person_history" (
193
193
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
194
194
  "workspace_id" uuid NOT NULL,
195
195
  "person_id" uuid NOT NULL,
@@ -201,7 +201,7 @@ CREATE TABLE "mod_hr"."person_history" (
201
201
  "source" text DEFAULT 'app' NOT NULL
202
202
  );
203
203
  --> statement-breakpoint
204
- CREATE TABLE "mod_hr"."positions" (
204
+ CREATE TABLE IF NOT EXISTS "mod_hr"."positions" (
205
205
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
206
206
  "workspace_id" uuid NOT NULL,
207
207
  "title" text NOT NULL,
@@ -212,25 +212,25 @@ CREATE TABLE "mod_hr"."positions" (
212
212
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
213
213
  );
214
214
  --> statement-breakpoint
215
- CREATE INDEX "hr_calendar_days_idx" ON "mod_hr"."calendar_days" USING btree ("workspace_id","calendar_id","date");--> statement-breakpoint
216
- CREATE UNIQUE INDEX "hr_calendar_days_uq" ON "mod_hr"."calendar_days" USING btree ("calendar_id","date","kind");--> statement-breakpoint
217
- CREATE INDEX "hr_calendars_ws_idx" ON "mod_hr"."calendars" USING btree ("workspace_id","archived_at");--> statement-breakpoint
218
- CREATE UNIQUE INDEX "hr_cost_centers_ws_code_uq" ON "mod_hr"."cost_centers" USING btree ("workspace_id","code");--> statement-breakpoint
219
- CREATE UNIQUE INDEX "hr_fields_ws_key_uq" ON "mod_hr"."custom_field_defs" USING btree ("workspace_id","key");--> statement-breakpoint
220
- CREATE INDEX "hr_employments_person_idx" ON "mod_hr"."employments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
221
- CREATE INDEX "hr_employments_ws_manager_idx" ON "mod_hr"."employments" USING btree ("workspace_id","manager_person_id");--> statement-breakpoint
222
- CREATE INDEX "hr_employments_ws_unit_idx" ON "mod_hr"."employments" USING btree ("workspace_id","org_unit_id");--> statement-breakpoint
223
- CREATE INDEX "hr_entities_ws_idx" ON "mod_hr"."legal_entities" USING btree ("workspace_id","archived_at");--> statement-breakpoint
224
- CREATE INDEX "hr_office_assign_person_idx" ON "mod_hr"."office_assignments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
225
- CREATE INDEX "hr_office_assign_office_idx" ON "mod_hr"."office_assignments" USING btree ("workspace_id","office_id","effective_from");--> statement-breakpoint
226
- CREATE INDEX "hr_offices_ws_idx" ON "mod_hr"."offices" USING btree ("workspace_id","archived_at");--> statement-breakpoint
227
- CREATE INDEX "hr_offices_ws_country_idx" ON "mod_hr"."offices" USING btree ("workspace_id","country");--> statement-breakpoint
228
- CREATE INDEX "hr_org_units_ws_idx" ON "mod_hr"."org_units" USING btree ("workspace_id","archived_at");--> statement-breakpoint
229
- CREATE INDEX "hr_people_ws_status_idx" ON "mod_hr"."people" USING btree ("workspace_id","status","display_name");--> statement-breakpoint
230
- CREATE UNIQUE INDEX "hr_people_ws_user_uq" ON "mod_hr"."people" USING btree ("workspace_id","user_id");--> statement-breakpoint
231
- CREATE UNIQUE INDEX "hr_people_ws_empno_uq" ON "mod_hr"."people" USING btree ("workspace_id","employee_no");--> statement-breakpoint
232
- CREATE INDEX "hr_people_sensitive_ws_idx" ON "mod_hr"."people_sensitive" USING btree ("workspace_id");--> statement-breakpoint
233
- CREATE INDEX "hr_person_docs_idx" ON "mod_hr"."person_documents" USING btree ("workspace_id","person_id","created_at");--> statement-breakpoint
234
- CREATE INDEX "hr_person_docs_expiry_idx" ON "mod_hr"."person_documents" USING btree ("workspace_id","expires_on");--> statement-breakpoint
235
- CREATE INDEX "hr_person_history_idx" ON "mod_hr"."person_history" USING btree ("workspace_id","person_id","created_at");--> statement-breakpoint
236
- CREATE INDEX "hr_positions_ws_idx" ON "mod_hr"."positions" USING btree ("workspace_id","archived_at");
215
+ CREATE INDEX IF NOT EXISTS "hr_calendar_days_idx" ON "mod_hr"."calendar_days" USING btree ("workspace_id","calendar_id","date");--> statement-breakpoint
216
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_calendar_days_uq" ON "mod_hr"."calendar_days" USING btree ("calendar_id","date","kind");--> statement-breakpoint
217
+ CREATE INDEX IF NOT EXISTS "hr_calendars_ws_idx" ON "mod_hr"."calendars" USING btree ("workspace_id","archived_at");--> statement-breakpoint
218
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_cost_centers_ws_code_uq" ON "mod_hr"."cost_centers" USING btree ("workspace_id","code");--> statement-breakpoint
219
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_fields_ws_key_uq" ON "mod_hr"."custom_field_defs" USING btree ("workspace_id","key");--> statement-breakpoint
220
+ CREATE INDEX IF NOT EXISTS "hr_employments_person_idx" ON "mod_hr"."employments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
221
+ CREATE INDEX IF NOT EXISTS "hr_employments_ws_manager_idx" ON "mod_hr"."employments" USING btree ("workspace_id","manager_person_id");--> statement-breakpoint
222
+ CREATE INDEX IF NOT EXISTS "hr_employments_ws_unit_idx" ON "mod_hr"."employments" USING btree ("workspace_id","org_unit_id");--> statement-breakpoint
223
+ CREATE INDEX IF NOT EXISTS "hr_entities_ws_idx" ON "mod_hr"."legal_entities" USING btree ("workspace_id","archived_at");--> statement-breakpoint
224
+ CREATE INDEX IF NOT EXISTS "hr_office_assign_person_idx" ON "mod_hr"."office_assignments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
225
+ CREATE INDEX IF NOT EXISTS "hr_office_assign_office_idx" ON "mod_hr"."office_assignments" USING btree ("workspace_id","office_id","effective_from");--> statement-breakpoint
226
+ CREATE INDEX IF NOT EXISTS "hr_offices_ws_idx" ON "mod_hr"."offices" USING btree ("workspace_id","archived_at");--> statement-breakpoint
227
+ CREATE INDEX IF NOT EXISTS "hr_offices_ws_country_idx" ON "mod_hr"."offices" USING btree ("workspace_id","country");--> statement-breakpoint
228
+ CREATE INDEX IF NOT EXISTS "hr_org_units_ws_idx" ON "mod_hr"."org_units" USING btree ("workspace_id","archived_at");--> statement-breakpoint
229
+ CREATE INDEX IF NOT EXISTS "hr_people_ws_status_idx" ON "mod_hr"."people" USING btree ("workspace_id","status","display_name");--> statement-breakpoint
230
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_people_ws_user_uq" ON "mod_hr"."people" USING btree ("workspace_id","user_id");--> statement-breakpoint
231
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_people_ws_empno_uq" ON "mod_hr"."people" USING btree ("workspace_id","employee_no");--> statement-breakpoint
232
+ CREATE INDEX IF NOT EXISTS "hr_people_sensitive_ws_idx" ON "mod_hr"."people_sensitive" USING btree ("workspace_id");--> statement-breakpoint
233
+ CREATE INDEX IF NOT EXISTS "hr_person_docs_idx" ON "mod_hr"."person_documents" USING btree ("workspace_id","person_id","created_at");--> statement-breakpoint
234
+ CREATE INDEX IF NOT EXISTS "hr_person_docs_expiry_idx" ON "mod_hr"."person_documents" USING btree ("workspace_id","expires_on");--> statement-breakpoint
235
+ CREATE INDEX IF NOT EXISTS "hr_person_history_idx" ON "mod_hr"."person_history" USING btree ("workspace_id","person_id","created_at");--> statement-breakpoint
236
+ CREATE INDEX IF NOT EXISTS "hr_positions_ws_idx" ON "mod_hr"."positions" USING btree ("workspace_id","archived_at");
@@ -9,84 +9,112 @@
9
9
 
10
10
  alter table "mod_hr"."legal_entities" enable row level security;--> statement-breakpoint
11
11
  alter table "mod_hr"."legal_entities" force row level security;--> statement-breakpoint
12
+ drop policy if exists "legal_entities_ws_isolation" on "mod_hr"."legal_entities";
13
+ --> statement-breakpoint
12
14
  create policy "legal_entities_ws_isolation" on "mod_hr"."legal_entities"
13
15
  using (workspace_id::text = current_setting('app.workspace_id', true))
14
16
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
15
17
 
16
18
  alter table "mod_hr"."offices" enable row level security;--> statement-breakpoint
17
19
  alter table "mod_hr"."offices" force row level security;--> statement-breakpoint
20
+ drop policy if exists "offices_ws_isolation" on "mod_hr"."offices";
21
+ --> statement-breakpoint
18
22
  create policy "offices_ws_isolation" on "mod_hr"."offices"
19
23
  using (workspace_id::text = current_setting('app.workspace_id', true))
20
24
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
21
25
 
22
26
  alter table "mod_hr"."cost_centers" enable row level security;--> statement-breakpoint
23
27
  alter table "mod_hr"."cost_centers" force row level security;--> statement-breakpoint
28
+ drop policy if exists "cost_centers_ws_isolation" on "mod_hr"."cost_centers";
29
+ --> statement-breakpoint
24
30
  create policy "cost_centers_ws_isolation" on "mod_hr"."cost_centers"
25
31
  using (workspace_id::text = current_setting('app.workspace_id', true))
26
32
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
27
33
 
28
34
  alter table "mod_hr"."org_units" enable row level security;--> statement-breakpoint
29
35
  alter table "mod_hr"."org_units" force row level security;--> statement-breakpoint
36
+ drop policy if exists "org_units_ws_isolation" on "mod_hr"."org_units";
37
+ --> statement-breakpoint
30
38
  create policy "org_units_ws_isolation" on "mod_hr"."org_units"
31
39
  using (workspace_id::text = current_setting('app.workspace_id', true))
32
40
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
33
41
 
34
42
  alter table "mod_hr"."positions" enable row level security;--> statement-breakpoint
35
43
  alter table "mod_hr"."positions" force row level security;--> statement-breakpoint
44
+ drop policy if exists "positions_ws_isolation" on "mod_hr"."positions";
45
+ --> statement-breakpoint
36
46
  create policy "positions_ws_isolation" on "mod_hr"."positions"
37
47
  using (workspace_id::text = current_setting('app.workspace_id', true))
38
48
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
39
49
 
40
50
  alter table "mod_hr"."people" enable row level security;--> statement-breakpoint
41
51
  alter table "mod_hr"."people" force row level security;--> statement-breakpoint
52
+ drop policy if exists "people_ws_isolation" on "mod_hr"."people";
53
+ --> statement-breakpoint
42
54
  create policy "people_ws_isolation" on "mod_hr"."people"
43
55
  using (workspace_id::text = current_setting('app.workspace_id', true))
44
56
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
45
57
 
46
58
  alter table "mod_hr"."people_sensitive" enable row level security;--> statement-breakpoint
47
59
  alter table "mod_hr"."people_sensitive" force row level security;--> statement-breakpoint
60
+ drop policy if exists "people_sensitive_ws_isolation" on "mod_hr"."people_sensitive";
61
+ --> statement-breakpoint
48
62
  create policy "people_sensitive_ws_isolation" on "mod_hr"."people_sensitive"
49
63
  using (workspace_id::text = current_setting('app.workspace_id', true))
50
64
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
51
65
 
52
66
  alter table "mod_hr"."employments" enable row level security;--> statement-breakpoint
53
67
  alter table "mod_hr"."employments" force row level security;--> statement-breakpoint
68
+ drop policy if exists "employments_ws_isolation" on "mod_hr"."employments";
69
+ --> statement-breakpoint
54
70
  create policy "employments_ws_isolation" on "mod_hr"."employments"
55
71
  using (workspace_id::text = current_setting('app.workspace_id', true))
56
72
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
57
73
 
58
74
  alter table "mod_hr"."office_assignments" enable row level security;--> statement-breakpoint
59
75
  alter table "mod_hr"."office_assignments" force row level security;--> statement-breakpoint
76
+ drop policy if exists "office_assignments_ws_isolation" on "mod_hr"."office_assignments";
77
+ --> statement-breakpoint
60
78
  create policy "office_assignments_ws_isolation" on "mod_hr"."office_assignments"
61
79
  using (workspace_id::text = current_setting('app.workspace_id', true))
62
80
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
63
81
 
64
82
  alter table "mod_hr"."person_history" enable row level security;--> statement-breakpoint
65
83
  alter table "mod_hr"."person_history" force row level security;--> statement-breakpoint
84
+ drop policy if exists "person_history_ws_isolation" on "mod_hr"."person_history";
85
+ --> statement-breakpoint
66
86
  create policy "person_history_ws_isolation" on "mod_hr"."person_history"
67
87
  using (workspace_id::text = current_setting('app.workspace_id', true))
68
88
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
69
89
 
70
90
  alter table "mod_hr"."person_documents" enable row level security;--> statement-breakpoint
71
91
  alter table "mod_hr"."person_documents" force row level security;--> statement-breakpoint
92
+ drop policy if exists "person_documents_ws_isolation" on "mod_hr"."person_documents";
93
+ --> statement-breakpoint
72
94
  create policy "person_documents_ws_isolation" on "mod_hr"."person_documents"
73
95
  using (workspace_id::text = current_setting('app.workspace_id', true))
74
96
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
75
97
 
76
98
  alter table "mod_hr"."custom_field_defs" enable row level security;--> statement-breakpoint
77
99
  alter table "mod_hr"."custom_field_defs" force row level security;--> statement-breakpoint
100
+ drop policy if exists "custom_field_defs_ws_isolation" on "mod_hr"."custom_field_defs";
101
+ --> statement-breakpoint
78
102
  create policy "custom_field_defs_ws_isolation" on "mod_hr"."custom_field_defs"
79
103
  using (workspace_id::text = current_setting('app.workspace_id', true))
80
104
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
81
105
 
82
106
  alter table "mod_hr"."calendars" enable row level security;--> statement-breakpoint
83
107
  alter table "mod_hr"."calendars" force row level security;--> statement-breakpoint
108
+ drop policy if exists "calendars_ws_isolation" on "mod_hr"."calendars";
109
+ --> statement-breakpoint
84
110
  create policy "calendars_ws_isolation" on "mod_hr"."calendars"
85
111
  using (workspace_id::text = current_setting('app.workspace_id', true))
86
112
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
87
113
 
88
114
  alter table "mod_hr"."calendar_days" enable row level security;--> statement-breakpoint
89
115
  alter table "mod_hr"."calendar_days" force row level security;--> statement-breakpoint
116
+ drop policy if exists "calendar_days_ws_isolation" on "mod_hr"."calendar_days";
117
+ --> statement-breakpoint
90
118
  create policy "calendar_days_ws_isolation" on "mod_hr"."calendar_days"
91
119
  using (workspace_id::text = current_setting('app.workspace_id', true))
92
120
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
@@ -100,13 +128,15 @@ create policy "calendar_days_ws_isolation" on "mod_hr"."calendar_days"
100
128
 
101
129
  -- One workspace, one default office. It is where a person with no assignment lands and where the
102
130
  -- resolution ladder bottoms out, so two of them would make "which calendar applies" ambiguous.
103
- create unique index "hr_offices_one_default_per_ws"
131
+ CREATE unique INDEX IF NOT EXISTS "hr_offices_one_default_per_ws"
104
132
  on "mod_hr"."offices" (workspace_id)
105
133
  where is_default;--> statement-breakpoint
106
134
 
107
135
  -- No two employment rows for one person may overlap. Without this, a backdated correction racing a
108
136
  -- forward-dated change leaves two rows in force on the same day, and "what was her FTE in March"
109
137
  -- has two answers.
138
+ alter table "mod_hr"."employments" drop constraint if exists "hr_employments_no_overlap";
139
+ --> statement-breakpoint
110
140
  alter table "mod_hr"."employments"
111
141
  add constraint "hr_employments_no_overlap"
112
142
  exclude using gist (
@@ -115,6 +145,8 @@ alter table "mod_hr"."employments"
115
145
  );--> statement-breakpoint
116
146
 
117
147
  -- Nor may one person hold the same office twice over an overlapping period.
148
+ alter table "mod_hr"."office_assignments" drop constraint if exists "hr_office_assignments_no_duplicate";
149
+ --> statement-breakpoint
118
150
  alter table "mod_hr"."office_assignments"
119
151
  add constraint "hr_office_assignments_no_duplicate"
120
152
  exclude using gist (
@@ -126,6 +158,8 @@ alter table "mod_hr"."office_assignments"
126
158
  -- And exactly one of a person's concurrent assignments may be primary. Only the primary office
127
159
  -- decides holidays, timezone and policy; two would mean two answers, which is the one thing the
128
160
  -- multi-office model must never allow.
161
+ alter table "mod_hr"."office_assignments" drop constraint if exists "hr_office_assignments_one_primary";
162
+ --> statement-breakpoint
129
163
  alter table "mod_hr"."office_assignments"
130
164
  add constraint "hr_office_assignments_one_primary"
131
165
  exclude using gist (
@@ -135,5 +169,5 @@ alter table "mod_hr"."office_assignments"
135
169
 
136
170
  -- An org unit's ltree path is unique within a workspace: two departments at the same path would
137
171
  -- make a subtree query return one of them arbitrarily.
138
- create unique index "hr_org_units_ws_path_uq" on "mod_hr"."org_units" (workspace_id, path);--> statement-breakpoint
139
- create index "hr_org_units_path_gist" on "mod_hr"."org_units" using gist (path);
172
+ CREATE unique INDEX IF NOT EXISTS "hr_org_units_ws_path_uq" on "mod_hr"."org_units" (workspace_id, path);--> statement-breakpoint
173
+ CREATE INDEX IF NOT EXISTS "hr_org_units_path_gist" on "mod_hr"."org_units" using gist (path);
@@ -1,4 +1,4 @@
1
- CREATE TABLE "mod_hr"."approval_chains" (
1
+ CREATE TABLE IF NOT EXISTS "mod_hr"."approval_chains" (
2
2
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
3
3
  "workspace_id" uuid NOT NULL,
4
4
  "name" text NOT NULL,
@@ -10,7 +10,7 @@ CREATE TABLE "mod_hr"."approval_chains" (
10
10
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
11
11
  );
12
12
  --> statement-breakpoint
13
- CREATE TABLE "mod_hr"."approval_decisions" (
13
+ CREATE TABLE IF NOT EXISTS "mod_hr"."approval_decisions" (
14
14
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
15
15
  "workspace_id" uuid NOT NULL,
16
16
  "step_id" uuid NOT NULL,
@@ -21,7 +21,7 @@ CREATE TABLE "mod_hr"."approval_decisions" (
21
21
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
22
22
  );
23
23
  --> statement-breakpoint
24
- CREATE TABLE "mod_hr"."approval_requests" (
24
+ CREATE TABLE IF NOT EXISTS "mod_hr"."approval_requests" (
25
25
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
26
26
  "workspace_id" uuid NOT NULL,
27
27
  "subject_type" text NOT NULL,
@@ -36,7 +36,7 @@ CREATE TABLE "mod_hr"."approval_requests" (
36
36
  "version" integer DEFAULT 0 NOT NULL
37
37
  );
38
38
  --> statement-breakpoint
39
- CREATE TABLE "mod_hr"."approval_steps" (
39
+ CREATE TABLE IF NOT EXISTS "mod_hr"."approval_steps" (
40
40
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
41
41
  "workspace_id" uuid NOT NULL,
42
42
  "request_id" uuid NOT NULL,
@@ -50,7 +50,7 @@ CREATE TABLE "mod_hr"."approval_steps" (
50
50
  "escalated_at" timestamp with time zone
51
51
  );
52
52
  --> statement-breakpoint
53
- CREATE TABLE "mod_hr"."delegations" (
53
+ CREATE TABLE IF NOT EXISTS "mod_hr"."delegations" (
54
54
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
55
55
  "workspace_id" uuid NOT NULL,
56
56
  "from_person_id" uuid NOT NULL,
@@ -62,7 +62,7 @@ CREATE TABLE "mod_hr"."delegations" (
62
62
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
63
63
  );
64
64
  --> statement-breakpoint
65
- CREATE TABLE "mod_hr"."leave_balance_cursor" (
65
+ CREATE TABLE IF NOT EXISTS "mod_hr"."leave_balance_cursor" (
66
66
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
67
67
  "workspace_id" uuid NOT NULL,
68
68
  "person_id" uuid NOT NULL,
@@ -74,7 +74,7 @@ CREATE TABLE "mod_hr"."leave_balance_cursor" (
74
74
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
75
75
  );
76
76
  --> statement-breakpoint
77
- CREATE TABLE "mod_hr"."leave_ledger" (
77
+ CREATE TABLE IF NOT EXISTS "mod_hr"."leave_ledger" (
78
78
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
79
79
  "workspace_id" uuid NOT NULL,
80
80
  "person_id" uuid NOT NULL,
@@ -91,7 +91,7 @@ CREATE TABLE "mod_hr"."leave_ledger" (
91
91
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
92
92
  );
93
93
  --> statement-breakpoint
94
- CREATE TABLE "mod_hr"."leave_request_days" (
94
+ CREATE TABLE IF NOT EXISTS "mod_hr"."leave_request_days" (
95
95
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
96
96
  "workspace_id" uuid NOT NULL,
97
97
  "request_id" uuid NOT NULL,
@@ -102,7 +102,7 @@ CREATE TABLE "mod_hr"."leave_request_days" (
102
102
  "status" text DEFAULT 'pending' NOT NULL
103
103
  );
104
104
  --> statement-breakpoint
105
- CREATE TABLE "mod_hr"."leave_requests" (
105
+ CREATE TABLE IF NOT EXISTS "mod_hr"."leave_requests" (
106
106
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
107
107
  "workspace_id" uuid NOT NULL,
108
108
  "person_id" uuid NOT NULL,
@@ -124,7 +124,7 @@ CREATE TABLE "mod_hr"."leave_requests" (
124
124
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
125
125
  );
126
126
  --> statement-breakpoint
127
- CREATE TABLE "mod_hr"."leave_types" (
127
+ CREATE TABLE IF NOT EXISTS "mod_hr"."leave_types" (
128
128
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
129
129
  "workspace_id" uuid NOT NULL,
130
130
  "key" text NOT NULL,
@@ -143,81 +143,101 @@ CREATE TABLE "mod_hr"."leave_types" (
143
143
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
144
144
  );
145
145
  --> statement-breakpoint
146
- CREATE INDEX "hr_approval_chains_idx" ON "mod_hr"."approval_chains" USING btree ("workspace_id","subject_type","archived_at");--> statement-breakpoint
147
- CREATE UNIQUE INDEX "hr_approval_decisions_uq" ON "mod_hr"."approval_decisions" USING btree ("step_id","approver_id");--> statement-breakpoint
148
- CREATE INDEX "hr_approval_requests_subject_idx" ON "mod_hr"."approval_requests" USING btree ("workspace_id","subject_type","subject_id");--> statement-breakpoint
149
- CREATE INDEX "hr_approval_requests_status_idx" ON "mod_hr"."approval_requests" USING btree ("workspace_id","status");--> statement-breakpoint
150
- CREATE UNIQUE INDEX "hr_approval_steps_uq" ON "mod_hr"."approval_steps" USING btree ("request_id","step_index");--> statement-breakpoint
151
- CREATE INDEX "hr_approval_steps_due_idx" ON "mod_hr"."approval_steps" USING btree ("workspace_id","status","due_at");--> statement-breakpoint
152
- CREATE INDEX "hr_delegations_idx" ON "mod_hr"."delegations" USING btree ("workspace_id","to_person_id","starts_on");--> statement-breakpoint
153
- CREATE UNIQUE INDEX "hr_balance_cursor_uq" ON "mod_hr"."leave_balance_cursor" USING btree ("workspace_id","person_id","leave_type_id","period_year");--> statement-breakpoint
154
- CREATE INDEX "hr_ledger_person_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","person_id","leave_type_id","effective_on");--> statement-breakpoint
155
- CREATE INDEX "hr_ledger_request_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","request_id");--> statement-breakpoint
156
- CREATE INDEX "hr_ledger_year_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","period_year");--> statement-breakpoint
157
- CREATE INDEX "hr_leave_days_person_idx" ON "mod_hr"."leave_request_days" USING btree ("workspace_id","person_id","date");--> statement-breakpoint
158
- CREATE INDEX "hr_leave_days_request_idx" ON "mod_hr"."leave_request_days" USING btree ("request_id");--> statement-breakpoint
159
- CREATE INDEX "hr_leave_requests_person_idx" ON "mod_hr"."leave_requests" USING btree ("workspace_id","person_id","starts_on");--> statement-breakpoint
160
- CREATE INDEX "hr_leave_requests_status_idx" ON "mod_hr"."leave_requests" USING btree ("workspace_id","status","starts_on");--> statement-breakpoint
161
- CREATE UNIQUE INDEX "hr_leave_requests_idem_uq" ON "mod_hr"."leave_requests" USING btree ("workspace_id","idempotency_key");--> statement-breakpoint
162
- CREATE UNIQUE INDEX "hr_leave_types_ws_key_uq" ON "mod_hr"."leave_types" USING btree ("workspace_id","key");--> statement-breakpoint
146
+ CREATE INDEX IF NOT EXISTS "hr_approval_chains_idx" ON "mod_hr"."approval_chains" USING btree ("workspace_id","subject_type","archived_at");--> statement-breakpoint
147
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_approval_decisions_uq" ON "mod_hr"."approval_decisions" USING btree ("step_id","approver_id");--> statement-breakpoint
148
+ CREATE INDEX IF NOT EXISTS "hr_approval_requests_subject_idx" ON "mod_hr"."approval_requests" USING btree ("workspace_id","subject_type","subject_id");--> statement-breakpoint
149
+ CREATE INDEX IF NOT EXISTS "hr_approval_requests_status_idx" ON "mod_hr"."approval_requests" USING btree ("workspace_id","status");--> statement-breakpoint
150
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_approval_steps_uq" ON "mod_hr"."approval_steps" USING btree ("request_id","step_index");--> statement-breakpoint
151
+ CREATE INDEX IF NOT EXISTS "hr_approval_steps_due_idx" ON "mod_hr"."approval_steps" USING btree ("workspace_id","status","due_at");--> statement-breakpoint
152
+ CREATE INDEX IF NOT EXISTS "hr_delegations_idx" ON "mod_hr"."delegations" USING btree ("workspace_id","to_person_id","starts_on");--> statement-breakpoint
153
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_balance_cursor_uq" ON "mod_hr"."leave_balance_cursor" USING btree ("workspace_id","person_id","leave_type_id","period_year");--> statement-breakpoint
154
+ CREATE INDEX IF NOT EXISTS "hr_ledger_person_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","person_id","leave_type_id","effective_on");--> statement-breakpoint
155
+ CREATE INDEX IF NOT EXISTS "hr_ledger_request_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","request_id");--> statement-breakpoint
156
+ CREATE INDEX IF NOT EXISTS "hr_ledger_year_idx" ON "mod_hr"."leave_ledger" USING btree ("workspace_id","period_year");--> statement-breakpoint
157
+ CREATE INDEX IF NOT EXISTS "hr_leave_days_person_idx" ON "mod_hr"."leave_request_days" USING btree ("workspace_id","person_id","date");--> statement-breakpoint
158
+ CREATE INDEX IF NOT EXISTS "hr_leave_days_request_idx" ON "mod_hr"."leave_request_days" USING btree ("request_id");--> statement-breakpoint
159
+ CREATE INDEX IF NOT EXISTS "hr_leave_requests_person_idx" ON "mod_hr"."leave_requests" USING btree ("workspace_id","person_id","starts_on");--> statement-breakpoint
160
+ CREATE INDEX IF NOT EXISTS "hr_leave_requests_status_idx" ON "mod_hr"."leave_requests" USING btree ("workspace_id","status","starts_on");--> statement-breakpoint
161
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_leave_requests_idem_uq" ON "mod_hr"."leave_requests" USING btree ("workspace_id","idempotency_key");--> statement-breakpoint
162
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_leave_types_ws_key_uq" ON "mod_hr"."leave_types" USING btree ("workspace_id","key");--> statement-breakpoint
163
163
  -- ---------------------------------------------------------------------------------------------
164
164
  -- Row-level security on the new tenant tables.
165
165
  alter table "mod_hr"."leave_types" enable row level security;--> statement-breakpoint
166
166
  alter table "mod_hr"."leave_types" force row level security;--> statement-breakpoint
167
+ drop policy if exists "leave_types_ws_isolation" on "mod_hr"."leave_types";
168
+ --> statement-breakpoint
167
169
  create policy "leave_types_ws_isolation" on "mod_hr"."leave_types"
168
170
  using (workspace_id::text = current_setting('app.workspace_id', true))
169
171
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
170
172
 
171
173
  alter table "mod_hr"."leave_ledger" enable row level security;--> statement-breakpoint
172
174
  alter table "mod_hr"."leave_ledger" force row level security;--> statement-breakpoint
175
+ drop policy if exists "leave_ledger_ws_isolation" on "mod_hr"."leave_ledger";
176
+ --> statement-breakpoint
173
177
  create policy "leave_ledger_ws_isolation" on "mod_hr"."leave_ledger"
174
178
  using (workspace_id::text = current_setting('app.workspace_id', true))
175
179
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
176
180
 
177
181
  alter table "mod_hr"."leave_balance_cursor" enable row level security;--> statement-breakpoint
178
182
  alter table "mod_hr"."leave_balance_cursor" force row level security;--> statement-breakpoint
183
+ drop policy if exists "leave_balance_cursor_ws_isolation" on "mod_hr"."leave_balance_cursor";
184
+ --> statement-breakpoint
179
185
  create policy "leave_balance_cursor_ws_isolation" on "mod_hr"."leave_balance_cursor"
180
186
  using (workspace_id::text = current_setting('app.workspace_id', true))
181
187
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
182
188
 
183
189
  alter table "mod_hr"."leave_requests" enable row level security;--> statement-breakpoint
184
190
  alter table "mod_hr"."leave_requests" force row level security;--> statement-breakpoint
191
+ drop policy if exists "leave_requests_ws_isolation" on "mod_hr"."leave_requests";
192
+ --> statement-breakpoint
185
193
  create policy "leave_requests_ws_isolation" on "mod_hr"."leave_requests"
186
194
  using (workspace_id::text = current_setting('app.workspace_id', true))
187
195
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
188
196
 
189
197
  alter table "mod_hr"."leave_request_days" enable row level security;--> statement-breakpoint
190
198
  alter table "mod_hr"."leave_request_days" force row level security;--> statement-breakpoint
199
+ drop policy if exists "leave_request_days_ws_isolation" on "mod_hr"."leave_request_days";
200
+ --> statement-breakpoint
191
201
  create policy "leave_request_days_ws_isolation" on "mod_hr"."leave_request_days"
192
202
  using (workspace_id::text = current_setting('app.workspace_id', true))
193
203
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
194
204
 
195
205
  alter table "mod_hr"."approval_chains" enable row level security;--> statement-breakpoint
196
206
  alter table "mod_hr"."approval_chains" force row level security;--> statement-breakpoint
207
+ drop policy if exists "approval_chains_ws_isolation" on "mod_hr"."approval_chains";
208
+ --> statement-breakpoint
197
209
  create policy "approval_chains_ws_isolation" on "mod_hr"."approval_chains"
198
210
  using (workspace_id::text = current_setting('app.workspace_id', true))
199
211
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
200
212
 
201
213
  alter table "mod_hr"."approval_requests" enable row level security;--> statement-breakpoint
202
214
  alter table "mod_hr"."approval_requests" force row level security;--> statement-breakpoint
215
+ drop policy if exists "approval_requests_ws_isolation" on "mod_hr"."approval_requests";
216
+ --> statement-breakpoint
203
217
  create policy "approval_requests_ws_isolation" on "mod_hr"."approval_requests"
204
218
  using (workspace_id::text = current_setting('app.workspace_id', true))
205
219
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
206
220
 
207
221
  alter table "mod_hr"."approval_steps" enable row level security;--> statement-breakpoint
208
222
  alter table "mod_hr"."approval_steps" force row level security;--> statement-breakpoint
223
+ drop policy if exists "approval_steps_ws_isolation" on "mod_hr"."approval_steps";
224
+ --> statement-breakpoint
209
225
  create policy "approval_steps_ws_isolation" on "mod_hr"."approval_steps"
210
226
  using (workspace_id::text = current_setting('app.workspace_id', true))
211
227
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
212
228
 
213
229
  alter table "mod_hr"."approval_decisions" enable row level security;--> statement-breakpoint
214
230
  alter table "mod_hr"."approval_decisions" force row level security;--> statement-breakpoint
231
+ drop policy if exists "approval_decisions_ws_isolation" on "mod_hr"."approval_decisions";
232
+ --> statement-breakpoint
215
233
  create policy "approval_decisions_ws_isolation" on "mod_hr"."approval_decisions"
216
234
  using (workspace_id::text = current_setting('app.workspace_id', true))
217
235
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
218
236
 
219
237
  alter table "mod_hr"."delegations" enable row level security;--> statement-breakpoint
220
238
  alter table "mod_hr"."delegations" force row level security;--> statement-breakpoint
239
+ drop policy if exists "delegations_ws_isolation" on "mod_hr"."delegations";
240
+ --> statement-breakpoint
221
241
  create policy "delegations_ws_isolation" on "mod_hr"."delegations"
222
242
  using (workspace_id::text = current_setting('app.workspace_id', true))
223
243
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
@@ -232,6 +252,6 @@ create policy "delegations_ws_isolation" on "mod_hr"."delegations"
232
252
  --
233
253
  -- Partial on purpose: a cancelled or rejected request must not block rebooking the same day, and a
234
254
  -- weekend inside a range is not counted so it does not conflict with anything either.
235
- create unique index "hr_leave_days_no_double_booking"
255
+ CREATE unique INDEX IF NOT EXISTS "hr_leave_days_no_double_booking"
236
256
  on "mod_hr"."leave_request_days" (workspace_id, person_id, date)
237
257
  where counted and status in ('pending', 'approved');
@@ -1,4 +1,4 @@
1
- CREATE TABLE "mod_hr"."attendance_days" (
1
+ CREATE TABLE IF NOT EXISTS "mod_hr"."attendance_days" (
2
2
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
3
3
  "workspace_id" uuid NOT NULL,
4
4
  "person_id" uuid NOT NULL,
@@ -19,7 +19,7 @@ CREATE TABLE "mod_hr"."attendance_days" (
19
19
  "computed_at" timestamp with time zone DEFAULT now() NOT NULL
20
20
  );
21
21
  --> statement-breakpoint
22
- CREATE TABLE "mod_hr"."punches" (
22
+ CREATE TABLE IF NOT EXISTS "mod_hr"."punches" (
23
23
  "id" uuid DEFAULT uuidv7() NOT NULL,
24
24
  "workspace_id" uuid NOT NULL,
25
25
  "person_id" uuid NOT NULL,
@@ -48,9 +48,11 @@ CREATE TABLE "mod_hr"."punches" (
48
48
  -- A partitioned table's primary key must contain the partition column, which is why it is
49
49
  -- (id, business_date) rather than (id). Same for the idempotency index: without business_date in it
50
50
  -- Postgres refuses to create it at all.
51
- ALTER TABLE "mod_hr"."punches" ADD PRIMARY KEY ("id", "business_date");
51
+ alter table "mod_hr"."punches" drop constraint if exists "punches_pkey";
52
52
  --> statement-breakpoint
53
- CREATE UNIQUE INDEX "hr_punches_idem_uq"
53
+ alter table "mod_hr"."punches" add constraint "punches_pkey" primary key ("id", "business_date");
54
+ --> statement-breakpoint
55
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_punches_idem_uq"
54
56
  ON "mod_hr"."punches" ("workspace_id", "idempotency_key", "business_date")
55
57
  WHERE "idempotency_key" IS NOT NULL;
56
58
  --> statement-breakpoint
@@ -64,11 +66,13 @@ ALTER TABLE "mod_hr"."punches_default" ENABLE ROW LEVEL SECURITY;
64
66
  --> statement-breakpoint
65
67
  ALTER TABLE "mod_hr"."punches_default" FORCE ROW LEVEL SECURITY;
66
68
  --> statement-breakpoint
69
+ drop policy if exists "punches_ws_isolation" on "mod_hr"."punches_default";
70
+ --> statement-breakpoint
67
71
  CREATE POLICY "punches_ws_isolation" ON "mod_hr"."punches_default"
68
72
  USING (workspace_id::text = current_setting('app.workspace_id', true))
69
73
  WITH CHECK (workspace_id::text = current_setting('app.workspace_id', true));
70
74
  --> statement-breakpoint
71
- -- Creating a partition is not just `CREATE TABLE ... PARTITION OF`.
75
+ -- Creating a partition is not just `CREATE TABLE IF NOT EXISTS ... PARTITION OF`.
72
76
  --
73
77
  -- A policy on a partitioned parent applies when you query **through the parent**. Query a partition
74
78
  -- directly and its own row-level security setting applies — and a fresh partition has none. Any
@@ -120,7 +124,7 @@ BEGIN
120
124
  END LOOP;
121
125
  END $$;
122
126
  --> statement-breakpoint
123
- CREATE TABLE "mod_hr"."regularizations" (
127
+ CREATE TABLE IF NOT EXISTS "mod_hr"."regularizations" (
124
128
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
125
129
  "workspace_id" uuid NOT NULL,
126
130
  "person_id" uuid NOT NULL,
@@ -134,7 +138,7 @@ CREATE TABLE "mod_hr"."regularizations" (
134
138
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
135
139
  );
136
140
  --> statement-breakpoint
137
- CREATE TABLE "mod_hr"."schedule_assignments" (
141
+ CREATE TABLE IF NOT EXISTS "mod_hr"."schedule_assignments" (
138
142
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
139
143
  "workspace_id" uuid NOT NULL,
140
144
  "person_id" uuid NOT NULL,
@@ -144,7 +148,7 @@ CREATE TABLE "mod_hr"."schedule_assignments" (
144
148
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
145
149
  );
146
150
  --> statement-breakpoint
147
- CREATE TABLE "mod_hr"."schedules" (
151
+ CREATE TABLE IF NOT EXISTS "mod_hr"."schedules" (
148
152
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
149
153
  "workspace_id" uuid NOT NULL,
150
154
  "name" text NOT NULL,
@@ -162,12 +166,12 @@ CREATE TABLE "mod_hr"."schedules" (
162
166
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
163
167
  );
164
168
  --> statement-breakpoint
165
- CREATE UNIQUE INDEX "hr_attendance_days_uq" ON "mod_hr"."attendance_days" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
166
- CREATE INDEX "hr_attendance_days_date_idx" ON "mod_hr"."attendance_days" USING btree ("workspace_id","business_date","status");--> statement-breakpoint
167
- CREATE INDEX "hr_punches_person_idx" ON "mod_hr"."punches" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
168
- CREATE INDEX "hr_regularizations_idx" ON "mod_hr"."regularizations" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
169
- CREATE INDEX "hr_schedule_assign_idx" ON "mod_hr"."schedule_assignments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
170
- CREATE INDEX "hr_schedules_ws_idx" ON "mod_hr"."schedules" USING btree ("workspace_id","archived_at");--> statement-breakpoint
169
+ CREATE UNIQUE INDEX IF NOT EXISTS "hr_attendance_days_uq" ON "mod_hr"."attendance_days" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
170
+ CREATE INDEX IF NOT EXISTS "hr_attendance_days_date_idx" ON "mod_hr"."attendance_days" USING btree ("workspace_id","business_date","status");--> statement-breakpoint
171
+ CREATE INDEX IF NOT EXISTS "hr_punches_person_idx" ON "mod_hr"."punches" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
172
+ CREATE INDEX IF NOT EXISTS "hr_regularizations_idx" ON "mod_hr"."regularizations" USING btree ("workspace_id","person_id","business_date");--> statement-breakpoint
173
+ CREATE INDEX IF NOT EXISTS "hr_schedule_assign_idx" ON "mod_hr"."schedule_assignments" USING btree ("workspace_id","person_id","effective_from");--> statement-breakpoint
174
+ CREATE INDEX IF NOT EXISTS "hr_schedules_ws_idx" ON "mod_hr"."schedules" USING btree ("workspace_id","archived_at");--> statement-breakpoint
171
175
  -- ---------------------------------------------------------------------------------------------
172
176
  -- Row-level security on the attendance tables.
173
177
  --
@@ -177,30 +181,40 @@ CREATE INDEX "hr_schedules_ws_idx" ON "mod_hr"."schedules" USING btree ("workspa
177
181
  -- true until a Postgres upgrade says otherwise.
178
182
  alter table "mod_hr"."schedules" enable row level security;--> statement-breakpoint
179
183
  alter table "mod_hr"."schedules" force row level security;--> statement-breakpoint
184
+ drop policy if exists "schedules_ws_isolation" on "mod_hr"."schedules";
185
+ --> statement-breakpoint
180
186
  create policy "schedules_ws_isolation" on "mod_hr"."schedules"
181
187
  using (workspace_id::text = current_setting('app.workspace_id', true))
182
188
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
183
189
 
184
190
  alter table "mod_hr"."schedule_assignments" enable row level security;--> statement-breakpoint
185
191
  alter table "mod_hr"."schedule_assignments" force row level security;--> statement-breakpoint
192
+ drop policy if exists "schedule_assignments_ws_isolation" on "mod_hr"."schedule_assignments";
193
+ --> statement-breakpoint
186
194
  create policy "schedule_assignments_ws_isolation" on "mod_hr"."schedule_assignments"
187
195
  using (workspace_id::text = current_setting('app.workspace_id', true))
188
196
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
189
197
 
190
198
  alter table "mod_hr"."punches" enable row level security;--> statement-breakpoint
191
199
  alter table "mod_hr"."punches" force row level security;--> statement-breakpoint
200
+ drop policy if exists "punches_ws_isolation" on "mod_hr"."punches";
201
+ --> statement-breakpoint
192
202
  create policy "punches_ws_isolation" on "mod_hr"."punches"
193
203
  using (workspace_id::text = current_setting('app.workspace_id', true))
194
204
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
195
205
 
196
206
  alter table "mod_hr"."attendance_days" enable row level security;--> statement-breakpoint
197
207
  alter table "mod_hr"."attendance_days" force row level security;--> statement-breakpoint
208
+ drop policy if exists "attendance_days_ws_isolation" on "mod_hr"."attendance_days";
209
+ --> statement-breakpoint
198
210
  create policy "attendance_days_ws_isolation" on "mod_hr"."attendance_days"
199
211
  using (workspace_id::text = current_setting('app.workspace_id', true))
200
212
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
201
213
 
202
214
  alter table "mod_hr"."regularizations" enable row level security;--> statement-breakpoint
203
215
  alter table "mod_hr"."regularizations" force row level security;--> statement-breakpoint
216
+ drop policy if exists "regularizations_ws_isolation" on "mod_hr"."regularizations";
217
+ --> statement-breakpoint
204
218
  create policy "regularizations_ws_isolation" on "mod_hr"."regularizations"
205
219
  using (workspace_id::text = current_setting('app.workspace_id', true))
206
220
  with check (workspace_id::text = current_setting('app.workspace_id', true));
@@ -1,4 +1,4 @@
1
- CREATE TABLE "mod_hr"."periods" (
1
+ CREATE TABLE IF NOT EXISTS "mod_hr"."periods" (
2
2
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
3
3
  "workspace_id" uuid NOT NULL,
4
4
  "kind" text DEFAULT 'payroll' NOT NULL,
@@ -12,7 +12,7 @@ CREATE TABLE "mod_hr"."periods" (
12
12
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
13
13
  );
14
14
  --> statement-breakpoint
15
- CREATE TABLE "mod_hr"."policies" (
15
+ CREATE TABLE IF NOT EXISTS "mod_hr"."policies" (
16
16
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
17
17
  "workspace_id" uuid NOT NULL,
18
18
  "kind" text NOT NULL,
@@ -28,7 +28,7 @@ CREATE TABLE "mod_hr"."policies" (
28
28
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL
29
29
  );
30
30
  --> statement-breakpoint
31
- CREATE TABLE "mod_hr"."policy_assignments" (
31
+ CREATE TABLE IF NOT EXISTS "mod_hr"."policy_assignments" (
32
32
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
33
33
  "workspace_id" uuid NOT NULL,
34
34
  "policy_id" uuid NOT NULL,
@@ -40,25 +40,31 @@ CREATE TABLE "mod_hr"."policy_assignments" (
40
40
  "created_at" timestamp with time zone DEFAULT now() NOT NULL
41
41
  );
42
42
  --> statement-breakpoint
43
- CREATE INDEX "hr_periods_idx" ON "mod_hr"."periods" USING btree ("workspace_id","kind","starts_on");--> statement-breakpoint
44
- CREATE INDEX "hr_policies_ws_kind_idx" ON "mod_hr"."policies" USING btree ("workspace_id","kind","effective_from");--> statement-breakpoint
45
- CREATE INDEX "hr_policy_assign_idx" ON "mod_hr"."policy_assignments" USING btree ("workspace_id","subject_kind","subject_id");--> statement-breakpoint
46
- CREATE INDEX "hr_policy_assign_policy_idx" ON "mod_hr"."policy_assignments" USING btree ("workspace_id","policy_id");--> statement-breakpoint
43
+ CREATE INDEX IF NOT EXISTS "hr_periods_idx" ON "mod_hr"."periods" USING btree ("workspace_id","kind","starts_on");--> statement-breakpoint
44
+ CREATE INDEX IF NOT EXISTS "hr_policies_ws_kind_idx" ON "mod_hr"."policies" USING btree ("workspace_id","kind","effective_from");--> statement-breakpoint
45
+ CREATE INDEX IF NOT EXISTS "hr_policy_assign_idx" ON "mod_hr"."policy_assignments" USING btree ("workspace_id","subject_kind","subject_id");--> statement-breakpoint
46
+ CREATE INDEX IF NOT EXISTS "hr_policy_assign_policy_idx" ON "mod_hr"."policy_assignments" USING btree ("workspace_id","policy_id");--> statement-breakpoint
47
47
  -- Row-level security on the policy and period tables.
48
48
  alter table "mod_hr"."policies" enable row level security;--> statement-breakpoint
49
49
  alter table "mod_hr"."policies" force row level security;--> statement-breakpoint
50
+ drop policy if exists "policies_ws_isolation" on "mod_hr"."policies";
51
+ --> statement-breakpoint
50
52
  create policy "policies_ws_isolation" on "mod_hr"."policies"
51
53
  using (workspace_id::text = current_setting('app.workspace_id', true))
52
54
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
53
55
 
54
56
  alter table "mod_hr"."policy_assignments" enable row level security;--> statement-breakpoint
55
57
  alter table "mod_hr"."policy_assignments" force row level security;--> statement-breakpoint
58
+ drop policy if exists "policy_assignments_ws_isolation" on "mod_hr"."policy_assignments";
59
+ --> statement-breakpoint
56
60
  create policy "policy_assignments_ws_isolation" on "mod_hr"."policy_assignments"
57
61
  using (workspace_id::text = current_setting('app.workspace_id', true))
58
62
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
59
63
 
60
64
  alter table "mod_hr"."periods" enable row level security;--> statement-breakpoint
61
65
  alter table "mod_hr"."periods" force row level security;--> statement-breakpoint
66
+ drop policy if exists "periods_ws_isolation" on "mod_hr"."periods";
67
+ --> statement-breakpoint
62
68
  create policy "periods_ws_isolation" on "mod_hr"."periods"
63
69
  using (workspace_id::text = current_setting('app.workspace_id', true))
64
70
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
@@ -68,6 +74,8 @@ create policy "periods_ws_isolation" on "mod_hr"."periods"
68
74
  -- Without this, two overlapping assignments at the same priority resolve arbitrarily: the ladder
69
75
  -- has a tie it cannot break, and which policy applies depends on row order. That is the kind of bug
70
76
  -- that shows up as two people on the same terms accruing differently.
77
+ alter table "mod_hr"."policy_assignments" drop constraint if exists "hr_policy_assign_no_overlap";
78
+ --> statement-breakpoint
71
79
  alter table "mod_hr"."policy_assignments"
72
80
  add constraint "hr_policy_assign_no_overlap"
73
81
  exclude using gist (
@@ -79,6 +87,8 @@ alter table "mod_hr"."policy_assignments"
79
87
 
80
88
  -- Two periods of a kind may not cover the same day for the same entity: "is this date locked" has
81
89
  -- to have exactly one answer.
90
+ alter table "mod_hr"."periods" drop constraint if exists "hr_periods_no_overlap";
91
+ --> statement-breakpoint
82
92
  alter table "mod_hr"."periods"
83
93
  add constraint "hr_periods_no_overlap"
84
94
  exclude using gist (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernhq/module-hr",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "Kern HR module: people, offices, org chart, calendars",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",