BEGIN; -- ============================================================================ -- LeAudit Platform Contract Template Schema -- 目标: -- 1. 在主库 leaudit_platform 创建 / 升级合同模板分类表 -- 2. 在主库 leaudit_platform 创建 / 升级合同模板主表 -- 3. 补齐地区字段、审计字段、软删除字段、索引与 updated_at 触发器 -- 说明: -- - 本脚本不依赖旧库 docauditai -- - 幂等脚本,可重复执行 -- ============================================================================ CREATE TABLE IF NOT EXISTS public.contract_categories ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, icon VARCHAR(100) NULL, description TEXT NULL, sort_order INTEGER NOT NULL DEFAULT 0, created_by BIGINT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_by BIGINT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deleted_at TIMESTAMPTZ NULL ); ALTER TABLE public.contract_categories ADD COLUMN IF NOT EXISTS icon VARCHAR(100), ADD COLUMN IF NOT EXISTS description TEXT, ADD COLUMN IF NOT EXISTS sort_order INTEGER NOT NULL DEFAULT 0, ADD COLUMN IF NOT EXISTS created_by BIGINT, ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), ADD COLUMN IF NOT EXISTS updated_by BIGINT, ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ; CREATE TABLE IF NOT EXISTS public.contract_templates ( id BIGSERIAL PRIMARY KEY, template_code VARCHAR(50) NOT NULL, title VARCHAR(200) NOT NULL, category_id INTEGER NOT NULL REFERENCES public.contract_categories(id) ON DELETE RESTRICT, region VARCHAR(50) NOT NULL DEFAULT '省级', description TEXT NULL, file_path VARCHAR(500) NULL, pdf_file_path VARCHAR(500) NULL, file_format VARCHAR(10) NOT NULL, original_file_name VARCHAR(500) NOT NULL DEFAULT '', mime_type VARCHAR(200) NULL, file_size BIGINT NOT NULL DEFAULT 0, pdf_file_size BIGINT NULL, is_featured BOOLEAN NOT NULL DEFAULT FALSE, created_by BIGINT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_by BIGINT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deleted_at TIMESTAMPTZ NULL ); ALTER TABLE public.contract_templates ADD COLUMN IF NOT EXISTS region VARCHAR(50) NOT NULL DEFAULT '省级', ADD COLUMN IF NOT EXISTS description TEXT, ADD COLUMN IF NOT EXISTS file_path VARCHAR(500), ADD COLUMN IF NOT EXISTS pdf_file_path VARCHAR(500), ADD COLUMN IF NOT EXISTS file_format VARCHAR(10), ADD COLUMN IF NOT EXISTS original_file_name VARCHAR(500) NOT NULL DEFAULT '', ADD COLUMN IF NOT EXISTS mime_type VARCHAR(200), ADD COLUMN IF NOT EXISTS file_size BIGINT NOT NULL DEFAULT 0, ADD COLUMN IF NOT EXISTS pdf_file_size BIGINT, ADD COLUMN IF NOT EXISTS is_featured BOOLEAN NOT NULL DEFAULT FALSE, ADD COLUMN IF NOT EXISTS created_by BIGINT, ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), ADD COLUMN IF NOT EXISTS updated_by BIGINT, ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ; UPDATE public.contract_templates SET region = '省级' WHERE region IS NULL OR BTRIM(region) = ''; UPDATE public.contract_templates SET original_file_name = COALESCE(NULLIF(original_file_name, ''), title || CASE WHEN file_format IS NOT NULL AND BTRIM(file_format) <> '' THEN '.' || LOWER(file_format) ELSE '' END) WHERE original_file_name IS NULL OR BTRIM(original_file_name) = ''; DO $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_indexes WHERE schemaname = 'public' AND indexname = 'idx_contract_categories_name' ) THEN EXECUTE 'DROP INDEX IF EXISTS public.idx_contract_categories_name'; END IF; IF EXISTS ( SELECT 1 FROM pg_indexes WHERE schemaname = 'public' AND indexname = 'idx_contract_templates_code' ) THEN EXECUTE 'DROP INDEX IF EXISTS public.idx_contract_templates_code'; END IF; END $$; CREATE UNIQUE INDEX IF NOT EXISTS uq_contract_categories_name_active ON public.contract_categories(name) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_contract_categories_sort_active ON public.contract_categories(sort_order) WHERE deleted_at IS NULL; CREATE UNIQUE INDEX IF NOT EXISTS uq_contract_templates_region_code_active ON public.contract_templates(region, template_code) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_contract_templates_region_active ON public.contract_templates(region) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_contract_templates_category_active ON public.contract_templates(category_id) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_contract_templates_updated_active ON public.contract_templates(updated_at DESC) WHERE deleted_at IS NULL; CREATE OR REPLACE FUNCTION update_contract_templates_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; DO $$ DECLARE t TEXT; BEGIN FOREACH t IN ARRAY ARRAY['contract_categories', 'contract_templates'] LOOP EXECUTE format('DROP TRIGGER IF EXISTS trg_%s_updated_at ON %I', t, t); EXECUTE format( 'CREATE TRIGGER trg_%s_updated_at BEFORE UPDATE ON %I FOR EACH ROW EXECUTE FUNCTION update_contract_templates_updated_at()', t, t ); END LOOP; END; $$; COMMENT ON TABLE public.contract_categories IS '合同模板分类表'; COMMENT ON COLUMN public.contract_categories.name IS '分类名称'; COMMENT ON COLUMN public.contract_categories.icon IS '分类图标'; COMMENT ON COLUMN public.contract_categories.description IS '分类描述'; COMMENT ON COLUMN public.contract_categories.sort_order IS '排序值'; COMMENT ON COLUMN public.contract_categories.created_by IS '创建人'; COMMENT ON COLUMN public.contract_categories.updated_by IS '更新人'; COMMENT ON COLUMN public.contract_categories.deleted_at IS '软删除时间'; COMMENT ON TABLE public.contract_templates IS '合同模板主表'; COMMENT ON COLUMN public.contract_templates.template_code IS '模板编码'; COMMENT ON COLUMN public.contract_templates.title IS '模板标题'; COMMENT ON COLUMN public.contract_templates.category_id IS '所属分类ID'; COMMENT ON COLUMN public.contract_templates.region IS '所属地区,省级模板使用“省级”'; COMMENT ON COLUMN public.contract_templates.description IS '模板描述'; COMMENT ON COLUMN public.contract_templates.file_path IS '源模板文件路径'; COMMENT ON COLUMN public.contract_templates.pdf_file_path IS 'PDF预览文件路径'; COMMENT ON COLUMN public.contract_templates.file_format IS '文件格式'; COMMENT ON COLUMN public.contract_templates.original_file_name IS '原始上传文件名'; COMMENT ON COLUMN public.contract_templates.mime_type IS '文件 MIME 类型'; COMMENT ON COLUMN public.contract_templates.file_size IS '主文件大小(字节)'; COMMENT ON COLUMN public.contract_templates.pdf_file_size IS '预览 PDF 文件大小(字节)'; COMMENT ON COLUMN public.contract_templates.is_featured IS '是否推荐模板'; COMMENT ON COLUMN public.contract_templates.created_by IS '创建人'; COMMENT ON COLUMN public.contract_templates.updated_by IS '更新人'; COMMENT ON COLUMN public.contract_templates.deleted_at IS '软删除时间'; COMMIT;