- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
136 lines
4.5 KiB
SQL
136 lines
4.5 KiB
SQL
-- 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";
|