-- User profile tabs (analogous to formTabs for users) CREATE TABLE IF NOT EXISTS "user_profile_tabs" ( "id" serial PRIMARY KEY NOT NULL, "organization_id" integer NOT NULL, "name" varchar(200) NOT NULL, "code" varchar(100) NOT NULL, "position" integer DEFAULT 0 NOT NULL, "display_order" integer DEFAULT 0, "created_at" timestamp DEFAULT now(), CONSTRAINT "user_profile_tabs_organization_id_code_unique" UNIQUE("organization_id","code") ); --> statement-breakpoint -- User profile fields (analogous to formFields for users) CREATE TABLE IF NOT EXISTS "user_profile_fields" ( "id" serial PRIMARY KEY NOT NULL, "organization_id" integer NOT NULL, "tab_id" integer, "name" varchar(200) NOT NULL, "code" varchar(100) NOT NULL, "type" varchar(50) NOT NULL, "is_required" boolean DEFAULT false, "placeholder" text, "default_value" text, "validation_rules" jsonb, "options" jsonb, "position" integer DEFAULT 0 NOT NULL, "display_order" integer DEFAULT 0, "linked_form_id" integer, "company_autofill" jsonb, "max_file_count" integer, "max_file_size_mb" integer, "auto_prolongation" boolean DEFAULT false, "auto_prolongation_label" text, "created_at" timestamp DEFAULT now(), CONSTRAINT "user_profile_fields_organization_id_code_unique" UNIQUE("organization_id","code") ); --> statement-breakpoint -- User profile field values (analogous to taskFieldValues for users) CREATE TABLE IF NOT EXISTS "user_profile_field_values" ( "id" serial PRIMARY KEY NOT NULL, "user_id" integer NOT NULL, "field_id" integer NOT NULL, "value" jsonb, "created_at" timestamp DEFAULT now(), "updated_at" timestamp DEFAULT now(), CONSTRAINT "user_profile_field_values_user_id_field_id_unique" UNIQUE("user_id","field_id") ); --> statement-breakpoint -- Foreign keys DO $$ BEGIN ALTER TABLE "user_profile_tabs" ADD CONSTRAINT "user_profile_tabs_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_profile_fields" ADD CONSTRAINT "user_profile_fields_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_profile_fields" ADD CONSTRAINT "user_profile_fields_tab_id_user_profile_tabs_id_fk" FOREIGN KEY ("tab_id") REFERENCES "user_profile_tabs"("id") ON DELETE set null ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_profile_fields" ADD CONSTRAINT "user_profile_fields_linked_form_id_forms_id_fk" FOREIGN KEY ("linked_form_id") REFERENCES "forms"("id") ON DELETE set null ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_profile_field_values" ADD CONSTRAINT "user_profile_field_values_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "user_profile_field_values" ADD CONSTRAINT "user_profile_field_values_field_id_user_profile_fields_id_fk" FOREIGN KEY ("field_id") REFERENCES "user_profile_fields"("id") ON DELETE cascade ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint -- Index for fast lookup CREATE INDEX IF NOT EXISTS "user_profile_field_values_user_field_idx" ON "user_profile_field_values" USING btree ("user_id","field_id"); --> statement-breakpoint -- Migrate existing user custom fields data (optional, preserves data) INSERT INTO "user_profile_fields" ("organization_id", "tab_id", "name", "code", "type", "is_required", "options", "position") SELECT "organization_id", NULL, "name", "code", "type", COALESCE("is_required", false), CASE WHEN "options" IS NOT NULL AND jsonb_typeof("options") = 'array' THEN "options" ELSE NULL END, COALESCE("position", 0) FROM "user_custom_fields"; --> statement-breakpoint -- Migrate existing user custom values (convert text to jsonb string) INSERT INTO "user_profile_field_values" ("user_id", "field_id", "value") SELECT ucv."user_id", upf."id", to_jsonb(ucv."value") FROM "user_custom_values" ucv JOIN "user_custom_fields" ucf ON ucv."field_id" = ucf."id" JOIN "user_profile_fields" upf ON upf."code" = ucf."code" AND upf."organization_id" = ucf."organization_id";