@kernhq/module-hr 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ CREATE TABLE "mod_hr"."periods" (
2
+ "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
3
+ "workspace_id" uuid NOT NULL,
4
+ "kind" text DEFAULT 'payroll' NOT NULL,
5
+ "legal_entity_id" uuid,
6
+ "starts_on" date NOT NULL,
7
+ "ends_on" date NOT NULL,
8
+ "status" text DEFAULT 'open' NOT NULL,
9
+ "locked_at" timestamp with time zone,
10
+ "locked_by" uuid,
11
+ "note" text,
12
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
13
+ );
14
+ --> statement-breakpoint
15
+ CREATE TABLE "mod_hr"."policies" (
16
+ "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
17
+ "workspace_id" uuid NOT NULL,
18
+ "kind" text NOT NULL,
19
+ "name" text NOT NULL,
20
+ "config" jsonb NOT NULL,
21
+ "effective_from" date NOT NULL,
22
+ "effective_to" date,
23
+ "source" text DEFAULT 'custom' NOT NULL,
24
+ "pack_key" text,
25
+ "config_hash" text DEFAULT '' NOT NULL,
26
+ "archived_at" timestamp with time zone,
27
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
28
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
29
+ );
30
+ --> statement-breakpoint
31
+ CREATE TABLE "mod_hr"."policy_assignments" (
32
+ "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
33
+ "workspace_id" uuid NOT NULL,
34
+ "policy_id" uuid NOT NULL,
35
+ "subject_kind" text NOT NULL,
36
+ "subject_id" uuid,
37
+ "effective_from" date NOT NULL,
38
+ "effective_to" date,
39
+ "priority" integer DEFAULT 0 NOT NULL,
40
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
41
+ );
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
47
+ -- Row-level security on the policy and period tables.
48
+ alter table "mod_hr"."policies" enable row level security;--> statement-breakpoint
49
+ alter table "mod_hr"."policies" force row level security;--> statement-breakpoint
50
+ create policy "policies_ws_isolation" on "mod_hr"."policies"
51
+ using (workspace_id::text = current_setting('app.workspace_id', true))
52
+ with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
53
+
54
+ alter table "mod_hr"."policy_assignments" enable row level security;--> statement-breakpoint
55
+ alter table "mod_hr"."policy_assignments" force row level security;--> statement-breakpoint
56
+ create policy "policy_assignments_ws_isolation" on "mod_hr"."policy_assignments"
57
+ using (workspace_id::text = current_setting('app.workspace_id', true))
58
+ with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
59
+
60
+ alter table "mod_hr"."periods" enable row level security;--> statement-breakpoint
61
+ alter table "mod_hr"."periods" force row level security;--> statement-breakpoint
62
+ create policy "periods_ws_isolation" on "mod_hr"."periods"
63
+ using (workspace_id::text = current_setting('app.workspace_id', true))
64
+ with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
65
+
66
+ -- One assignment of a policy at a rung over a period.
67
+ --
68
+ -- Without this, two overlapping assignments at the same priority resolve arbitrarily: the ladder
69
+ -- has a tie it cannot break, and which policy applies depends on row order. That is the kind of bug
70
+ -- that shows up as two people on the same terms accruing differently.
71
+ alter table "mod_hr"."policy_assignments"
72
+ add constraint "hr_policy_assign_no_overlap"
73
+ exclude using gist (
74
+ policy_id with =,
75
+ subject_kind with =,
76
+ coalesce(subject_id, '00000000-0000-0000-0000-000000000000'::uuid) with =,
77
+ daterange(effective_from, effective_to, '[]') with &&
78
+ );--> statement-breakpoint
79
+
80
+ -- Two periods of a kind may not cover the same day for the same entity: "is this date locked" has
81
+ -- to have exactly one answer.
82
+ alter table "mod_hr"."periods"
83
+ add constraint "hr_periods_no_overlap"
84
+ exclude using gist (
85
+ kind with =,
86
+ workspace_id with =,
87
+ coalesce(legal_entity_id, '00000000-0000-0000-0000-000000000000'::uuid) with =,
88
+ daterange(starts_on, ends_on, '[]') with &&
89
+ );