feat(documents): папки шаблонов, маппинги и поле document_template; fix(batch): атомарное создание задач, idempotency и массовое удаление в реестре
This commit is contained in:
53
migrations/0040_document_template_folders_and_targets.sql
Normal file
53
migrations/0040_document_template_folders_and_targets.sql
Normal file
@@ -0,0 +1,53 @@
|
||||
-- Document Center: template folders, folder-level variable mappings, and generation targets
|
||||
-- Safe to run multiple times (CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "document_template_folders" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"organization_id" integer NOT NULL,
|
||||
"parent_id" integer,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"position" integer DEFAULT 0 NOT NULL,
|
||||
"created_at" timestamp DEFAULT now(),
|
||||
"updated_at" timestamp DEFAULT now()
|
||||
);
|
||||
--> statement-breakpoint
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "document_folder_mappings" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"folder_id" integer NOT NULL,
|
||||
"code" varchar(100) NOT NULL,
|
||||
"label" varchar(200),
|
||||
"description" text,
|
||||
"source" varchar(30) NOT NULL,
|
||||
"mapping" jsonb DEFAULT '{}'::jsonb,
|
||||
"default_value" text,
|
||||
"sort_order" integer DEFAULT 0,
|
||||
"created_at" timestamp DEFAULT now()
|
||||
);
|
||||
--> statement-breakpoint
|
||||
|
||||
-- Add folder and target columns to document_templates
|
||||
ALTER TABLE "document_templates" ADD COLUMN IF NOT EXISTS "folder_id" integer;
|
||||
ALTER TABLE "document_templates" ADD COLUMN IF NOT EXISTS "target_form_id" integer;
|
||||
ALTER TABLE "document_templates" ADD COLUMN IF NOT EXISTS "target_field_code" varchar(100);
|
||||
ALTER TABLE "document_templates" ADD COLUMN IF NOT EXISTS "target_task_source" varchar(20) DEFAULT 'current';
|
||||
ALTER TABLE "document_templates" ADD COLUMN IF NOT EXISTS "target_source_field_code" varchar(100);
|
||||
|
||||
-- Foreign keys
|
||||
ALTER TABLE "document_template_folders" DROP CONSTRAINT IF EXISTS "document_template_folders_organization_id_organizations_id_fk";
|
||||
ALTER TABLE "document_template_folders" ADD CONSTRAINT "document_template_folders_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE cascade;
|
||||
-- parent_id не объявляем как FK, чтобы избежать циклической ссылки в Drizzle ORM (как у других деревьев: form_folders, directory_folders, roles)
|
||||
|
||||
ALTER TABLE "document_folder_mappings" DROP CONSTRAINT IF EXISTS "document_folder_mappings_folder_id_document_template_folders_id_fk";
|
||||
ALTER TABLE "document_folder_mappings" ADD CONSTRAINT "document_folder_mappings_folder_id_document_template_folders_id_fk" FOREIGN KEY ("folder_id") REFERENCES "document_template_folders"("id") ON DELETE cascade;
|
||||
|
||||
ALTER TABLE "document_templates" DROP CONSTRAINT IF EXISTS "document_templates_folder_id_document_template_folders_id_fk";
|
||||
ALTER TABLE "document_templates" ADD CONSTRAINT "document_templates_folder_id_document_template_folders_id_fk" FOREIGN KEY ("folder_id") REFERENCES "document_template_folders"("id") ON DELETE set null;
|
||||
ALTER TABLE "document_templates" DROP CONSTRAINT IF EXISTS "document_templates_target_form_id_forms_id_fk";
|
||||
ALTER TABLE "document_templates" ADD CONSTRAINT "document_templates_target_form_id_forms_id_fk" FOREIGN KEY ("target_form_id") REFERENCES "forms"("id") ON DELETE set null;
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS "document_template_folders_org_parent_idx" ON "document_template_folders" ("organization_id", "parent_id");
|
||||
CREATE INDEX IF NOT EXISTS "document_template_folders_position_idx" ON "document_template_folders" ("position");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "document_folder_mappings_code_unique" ON "document_folder_mappings" ("folder_id", "code");
|
||||
CREATE INDEX IF NOT EXISTS "document_templates_org_folder_idx" ON "document_templates" ("organization_id", "folder_id");
|
||||
23
migrations/0052_idempotency_keys.sql
Normal file
23
migrations/0052_idempotency_keys.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Idempotency keys for batch task creation and other heavy write endpoints
|
||||
CREATE TABLE IF NOT EXISTS idempotency_keys (
|
||||
id SERIAL PRIMARY KEY,
|
||||
key VARCHAR(255) NOT NULL,
|
||||
organization_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
endpoint VARCHAR(255) NOT NULL,
|
||||
payload_hash VARCHAR(64) NOT NULL,
|
||||
response_json JSONB NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
expires_at TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idempotency_keys_org_key_idx ON idempotency_keys(organization_id, key);
|
||||
CREATE INDEX IF NOT EXISTS idempotency_keys_expires_at_idx ON idempotency_keys(expires_at);
|
||||
|
||||
-- Enable tenant isolation for idempotency keys
|
||||
ALTER TABLE idempotency_keys ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS tenant_iso ON idempotency_keys;
|
||||
CREATE POLICY tenant_iso ON idempotency_keys USING (
|
||||
current_setting('app.is_superadmin', true) = 'true'
|
||||
OR organization_id = NULLIF(current_setting('app.current_org_id', true), '')::int
|
||||
);
|
||||
@@ -148,6 +148,13 @@
|
||||
"when": 1783000000000,
|
||||
"tag": "0039_add_asset_form_link",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"version": "7",
|
||||
"when": 1783000001000,
|
||||
"tag": "0040_document_template_folders_and_targets",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user