feat: add NV Bühne non-renewal & compensation module (Phase 3.2)

Implement § 61 NV Bühne non-renewal deadline calculation with tiered
protection (standard 31.10., extended 31.07. for 15+ years, special
protection for over-55), tariff-based compensation calculation with
Gagenklassen and Dienstalterszulage, and Spielzeit seasonal logic
(1.8.–31.7. with Probenzeit). Includes DB schema (contracts,
compensationRules, nonRenewalDeadlines), migration, and three API
endpoints under /api/nv-buehne/.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO (LegalAI)
2026-04-08 23:25:54 +00:00
parent a7245001ad
commit 3c16fdc30f
9 changed files with 1348 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
CREATE TYPE "public"."contract_status" AS ENUM('aktiv', 'gekuendigt', 'nichtverlaengert', 'ausgelaufen', 'ruhend');--> statement-breakpoint
CREATE TYPE "public"."compensation_component" AS ENUM('grundgage', 'ortszuschlag', 'kinderzuschlag', 'dienstalterszulage', 'funktionszulage', 'sonderzahlung', 'probenzuschlag');--> statement-breakpoint
CREATE TABLE "contracts" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"tenant_id" uuid NOT NULL,
"case_id" uuid,
"artist_name" varchar(255) NOT NULL,
"theater_name" varchar(255) NOT NULL,
"fachgruppe_id" uuid,
"status" "contract_status" DEFAULT 'aktiv' NOT NULL,
"contract_start" date NOT NULL,
"contract_end" date NOT NULL,
"years_of_service" integer DEFAULT 0 NOT NULL,
"is_first_engagement" boolean DEFAULT false,
"is_over_55" boolean DEFAULT false,
"current_spielzeit" varchar(20),
"gagenklasse" varchar(50),
"monthly_gross_cents" integer,
"notes" text,
"metadata" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "compensation_rules" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"tenant_id" uuid,
"fachgruppe_id" uuid,
"component" "compensation_component" NOT NULL,
"gagenklasse" varchar(50),
"label" varchar(255) NOT NULL,
"amount_cents" integer NOT NULL,
"min_years_of_service" integer DEFAULT 0,
"max_years_of_service" integer,
"valid_from_spielzeit" varchar(20),
"valid_to_spielzeit" varchar(20),
"legal_basis" varchar(255),
"description" text,
"sort_order" integer DEFAULT 0,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "non_renewal_deadlines" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"contract_id" uuid NOT NULL,
"spielzeit" varchar(20) NOT NULL,
"deadline_date" date NOT NULL,
"warning_date" date,
"warning_days_before" integer DEFAULT 30,
"notice_sent" boolean DEFAULT false,
"notice_sent_date" date,
"is_auto_renewed" boolean DEFAULT false,
"legal_basis" varchar(255) NOT NULL,
"calculation_basis" text,
"protection_category" varchar(100),
"notes" text,
"created_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "contracts" ADD CONSTRAINT "contracts_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contracts" ADD CONSTRAINT "contracts_case_id_cases_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."cases"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "contracts" ADD CONSTRAINT "contracts_fachgruppe_id_nv_buehne_fachgruppen_id_fk" FOREIGN KEY ("fachgruppe_id") REFERENCES "public"."nv_buehne_fachgruppen"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "compensation_rules" ADD CONSTRAINT "compensation_rules_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "compensation_rules" ADD CONSTRAINT "compensation_rules_fachgruppe_id_nv_buehne_fachgruppen_id_fk" FOREIGN KEY ("fachgruppe_id") REFERENCES "public"."nv_buehne_fachgruppen"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "non_renewal_deadlines" ADD CONSTRAINT "non_renewal_deadlines_contract_id_contracts_id_fk" FOREIGN KEY ("contract_id") REFERENCES "public"."contracts"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "contracts_tenant_idx" ON "contracts" USING btree ("tenant_id");--> statement-breakpoint
CREATE INDEX "contracts_case_idx" ON "contracts" USING btree ("case_id");--> statement-breakpoint
CREATE INDEX "contracts_fachgruppe_idx" ON "contracts" USING btree ("fachgruppe_id");--> statement-breakpoint
CREATE INDEX "contracts_status_idx" ON "contracts" USING btree ("status");--> statement-breakpoint
CREATE INDEX "contracts_end_idx" ON "contracts" USING btree ("contract_end");--> statement-breakpoint
CREATE INDEX "compensation_rules_tenant_idx" ON "compensation_rules" USING btree ("tenant_id");--> statement-breakpoint
CREATE INDEX "compensation_rules_fachgruppe_idx" ON "compensation_rules" USING btree ("fachgruppe_id");--> statement-breakpoint
CREATE INDEX "compensation_rules_component_idx" ON "compensation_rules" USING btree ("component");--> statement-breakpoint
CREATE INDEX "compensation_rules_gagenklasse_idx" ON "compensation_rules" USING btree ("gagenklasse");--> statement-breakpoint
CREATE INDEX "non_renewal_deadlines_contract_idx" ON "non_renewal_deadlines" USING btree ("contract_id");--> statement-breakpoint
CREATE INDEX "non_renewal_deadlines_date_idx" ON "non_renewal_deadlines" USING btree ("deadline_date");--> statement-breakpoint
CREATE INDEX "non_renewal_deadlines_spielzeit_idx" ON "non_renewal_deadlines" USING btree ("spielzeit");