BEGIN; -- ============================================================================ -- Rule Domain Tenant Phase 1 -- 目标: -- 1. 为规则域核心表补 tenant_code / scope_type / 运行结果快照字段 -- 2. 为运行时 TENANT -> PROVINCIAL -> PUBLIC 解析建立物理载体 -- 3. 将历史全局规则资产默认回填到 PROVINCIAL,而不是 PUBLIC -- 说明: -- - 本阶段只做补列、建索引、基础回填 -- - 不强制 NOT NULL -- - 不删除旧 region / 全局兼容逻辑 -- ============================================================================ -- -------------------------------------------------------------------------- -- 1. leaudit_rule_sets -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_rule_sets ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS scope_type VARCHAR(32) DEFAULT 'PROVINCIAL', ADD COLUMN IF NOT EXISTS source_rule_set_id BIGINT, ADD COLUMN IF NOT EXISTS tenant_name_snapshot VARCHAR(255); COMMENT ON COLUMN public.leaudit_rule_sets.tenant_code IS '规则集所属租户编码'; COMMENT ON COLUMN public.leaudit_rule_sets.scope_type IS '规则集作用域: TENANT / PROVINCIAL / PUBLIC'; COMMENT ON COLUMN public.leaudit_rule_sets.source_rule_set_id IS '派生规则集来源 rule_set_id'; COMMENT ON COLUMN public.leaudit_rule_sets.tenant_name_snapshot IS '规则集所属租户名称快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_sets_tenant_code ON public.leaudit_rule_sets(tenant_code) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_sets_scope_type ON public.leaudit_rule_sets(scope_type) WHERE deleted_at IS NULL; -- -------------------------------------------------------------------------- -- 2. leaudit_rule_versions -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_rule_versions ADD COLUMN IF NOT EXISTS tenant_code_snapshot VARCHAR(64), ADD COLUMN IF NOT EXISTS scope_type_snapshot VARCHAR(32), ADD COLUMN IF NOT EXISTS source_version_id BIGINT; COMMENT ON COLUMN public.leaudit_rule_versions.tenant_code_snapshot IS '规则版本所属租户编码快照'; COMMENT ON COLUMN public.leaudit_rule_versions.scope_type_snapshot IS '规则版本作用域快照'; COMMENT ON COLUMN public.leaudit_rule_versions.source_version_id IS '派生版本来源 version_id'; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_versions_tenant_code_snapshot ON public.leaudit_rule_versions(tenant_code_snapshot); -- -------------------------------------------------------------------------- -- 3. leaudit_rule_group_bindings -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_rule_group_bindings ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS scope_type VARCHAR(32) DEFAULT 'PROVINCIAL', ADD COLUMN IF NOT EXISTS tenant_name_snapshot VARCHAR(255); COMMENT ON COLUMN public.leaudit_rule_group_bindings.tenant_code IS '业务组绑定所属租户编码'; COMMENT ON COLUMN public.leaudit_rule_group_bindings.scope_type IS '业务组绑定作用域: TENANT / PROVINCIAL / PUBLIC'; COMMENT ON COLUMN public.leaudit_rule_group_bindings.tenant_name_snapshot IS '业务组绑定所属租户名称快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_group_bindings_group_tenant ON public.leaudit_rule_group_bindings(group_id, tenant_code) WHERE deleted_at IS NULL; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_group_bindings_scope_type ON public.leaudit_rule_group_bindings(scope_type) WHERE deleted_at IS NULL; -- -------------------------------------------------------------------------- -- 4. leaudit_rule_type_bindings -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_rule_type_bindings ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS scope_type VARCHAR(32) DEFAULT 'PROVINCIAL'; COMMENT ON COLUMN public.leaudit_rule_type_bindings.tenant_code IS '旧规则类型绑定所属租户编码,仅用于兼容与迁移'; COMMENT ON COLUMN public.leaudit_rule_type_bindings.scope_type IS '旧规则类型绑定作用域,仅用于兼容与迁移'; -- -------------------------------------------------------------------------- -- 5. leaudit_audit_runs -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_audit_runs ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS tenant_name_snapshot VARCHAR(255), ADD COLUMN IF NOT EXISTS scope_type_snapshot VARCHAR(32), ADD COLUMN IF NOT EXISTS group_id_snapshot BIGINT, ADD COLUMN IF NOT EXISTS rule_binding_id_snapshot BIGINT; COMMENT ON COLUMN public.leaudit_audit_runs.tenant_code IS '本次运行所属租户编码快照'; COMMENT ON COLUMN public.leaudit_audit_runs.tenant_name_snapshot IS '本次运行所属租户名称快照'; COMMENT ON COLUMN public.leaudit_audit_runs.scope_type_snapshot IS '本次运行命中的规则作用域快照'; COMMENT ON COLUMN public.leaudit_audit_runs.group_id_snapshot IS '本次运行命中的业务组快照'; COMMENT ON COLUMN public.leaudit_audit_runs.rule_binding_id_snapshot IS '本次运行命中的规则绑定快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_audit_runs_tenant_code ON public.leaudit_audit_runs(tenant_code, created_at DESC); -- -------------------------------------------------------------------------- -- 6. leaudit_rule_results -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_rule_results ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS tenant_name_snapshot VARCHAR(255); COMMENT ON COLUMN public.leaudit_rule_results.tenant_code IS '规则结果所属租户编码快照'; COMMENT ON COLUMN public.leaudit_rule_results.tenant_name_snapshot IS '规则结果所属租户名称快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_rule_results_tenant_code ON public.leaudit_rule_results(tenant_code); -- -------------------------------------------------------------------------- -- 7. leaudit_run_errors -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_run_errors ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64), ADD COLUMN IF NOT EXISTS tenant_name_snapshot VARCHAR(255); COMMENT ON COLUMN public.leaudit_run_errors.tenant_code IS '运行错误所属租户编码快照'; COMMENT ON COLUMN public.leaudit_run_errors.tenant_name_snapshot IS '运行错误所属租户名称快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_run_errors_tenant_code ON public.leaudit_run_errors(tenant_code); -- -------------------------------------------------------------------------- -- 8. leaudit_run_metrics -- -------------------------------------------------------------------------- ALTER TABLE public.leaudit_run_metrics ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64); COMMENT ON COLUMN public.leaudit_run_metrics.tenant_code IS '运行指标所属租户编码快照'; CREATE INDEX IF NOT EXISTS idx_leaudit_run_metrics_tenant_code ON public.leaudit_run_metrics(tenant_code); -- -------------------------------------------------------------------------- -- 9. 历史资产默认回填到 PROVINCIAL -- -------------------------------------------------------------------------- UPDATE public.leaudit_rule_sets SET tenant_code = COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL'), scope_type = COALESCE(NULLIF(BTRIM(scope_type), ''), 'PROVINCIAL') WHERE deleted_at IS NULL; -- 兼容历史唯一约束 (rule_type, region):租户私有规则集必须使用租户编码作为 legacy region, -- 否则会与省级默认 region=default 冲突。 UPDATE public.leaudit_rule_sets SET region = tenant_code WHERE deleted_at IS NULL AND scope_type = 'TENANT' AND tenant_code IS NOT NULL AND BTRIM(tenant_code) <> '' AND region = 'default'; UPDATE public.leaudit_rule_versions rv SET tenant_code_snapshot = COALESCE( NULLIF(BTRIM(rv.tenant_code_snapshot), ''), NULLIF(BTRIM(rs.tenant_code), ''), 'PROVINCIAL' ), scope_type_snapshot = COALESCE( NULLIF(BTRIM(rv.scope_type_snapshot), ''), NULLIF(BTRIM(rs.scope_type), ''), 'PROVINCIAL' ) FROM public.leaudit_rule_sets rs WHERE rv.rule_set_id = rs.id; UPDATE public.leaudit_rule_group_bindings rgb SET tenant_code = COALESCE(NULLIF(BTRIM(rgb.tenant_code), ''), 'PROVINCIAL'), scope_type = COALESCE(NULLIF(BTRIM(rgb.scope_type), ''), 'PROVINCIAL') WHERE rgb.deleted_at IS NULL; UPDATE public.leaudit_rule_type_bindings SET tenant_code = COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL'), scope_type = COALESCE(NULLIF(BTRIM(scope_type), ''), 'PROVINCIAL') WHERE deleted_at IS NULL; -- -------------------------------------------------------------------------- -- 10. 运行与结果快照回填 -- -------------------------------------------------------------------------- UPDATE public.leaudit_audit_runs ar SET tenant_code = COALESCE( NULLIF(BTRIM(ar.tenant_code), ''), NULLIF(BTRIM(d.tenant_code), ''), 'PROVINCIAL' ), scope_type_snapshot = COALESCE( NULLIF(BTRIM(ar.scope_type_snapshot), ''), 'PROVINCIAL' ), group_id_snapshot = COALESCE(ar.group_id_snapshot, d.group_id) FROM public.leaudit_documents d WHERE ar.document_id = d.id; UPDATE public.leaudit_rule_results rr SET tenant_code = COALESCE( NULLIF(BTRIM(rr.tenant_code), ''), NULLIF(BTRIM(ar.tenant_code), ''), NULLIF(BTRIM(d.tenant_code), ''), 'PROVINCIAL' ) FROM public.leaudit_audit_runs ar LEFT JOIN public.leaudit_documents d ON d.id = ar.document_id WHERE rr.run_id = ar.id; UPDATE public.leaudit_run_errors re SET tenant_code = COALESCE( NULLIF(BTRIM(re.tenant_code), ''), NULLIF(BTRIM(ar.tenant_code), ''), NULLIF(BTRIM(d.tenant_code), ''), 'PROVINCIAL' ) FROM public.leaudit_audit_runs ar LEFT JOIN public.leaudit_documents d ON d.id = ar.document_id WHERE re.run_id = ar.id; UPDATE public.leaudit_run_metrics rm SET tenant_code = COALESCE( NULLIF(BTRIM(rm.tenant_code), ''), NULLIF(BTRIM(ar.tenant_code), ''), NULLIF(BTRIM(d.tenant_code), ''), 'PROVINCIAL' ) FROM public.leaudit_audit_runs ar LEFT JOIN public.leaudit_documents d ON d.id = ar.document_id WHERE rm.run_id = ar.id; COMMIT;