feat: add backend rule group and permission support
This commit is contained in:
@@ -0,0 +1,462 @@
|
||||
-- 评查点分组正式迁移脚本(业务大类根版本)
|
||||
-- 目标:
|
||||
-- 一级分组 = 业务大类(合同 / 行政卷宗 / 后续新增业务)
|
||||
-- 二级分组 = 具体业务类型
|
||||
-- 规则集 = 挂在二级分组下
|
||||
-- 入口模块 = 绑定一级分组
|
||||
--
|
||||
-- 重要说明:
|
||||
-- 1. 本脚本面向当前真实库结构:
|
||||
-- - 已存在旧一级根(一级=具体文档类型)
|
||||
-- - 已存在新一级业务根 root.contract / root.casefile
|
||||
-- - 已存在默认二级分组 *.default / 通用
|
||||
-- 2. 执行前必须先跑:
|
||||
-- scripts/precheck_rule_group_migration.sql
|
||||
-- 3. 必须先备份:
|
||||
-- leaudit_evaluation_point_groups
|
||||
-- leaudit_rule_group_bindings
|
||||
-- leaudit_rule_type_bindings
|
||||
-- leaudit_document_types
|
||||
-- 4. 本脚本不会立刻删除旧一级根,只做结构补齐 + 绑定迁移 + 汇总重建。
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- =========================================================
|
||||
-- 0. 补齐结构:一级分组入口模块字段
|
||||
-- =========================================================
|
||||
ALTER TABLE leaudit_evaluation_point_groups
|
||||
ADD COLUMN IF NOT EXISTS entry_module_id BIGINT NULL REFERENCES leaudit_entry_modules(id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_leaudit_ep_groups_entry_module
|
||||
ON leaudit_evaluation_point_groups(entry_module_id);
|
||||
|
||||
-- =========================================================
|
||||
-- 1. 保证一级业务大类根存在,并统一编码
|
||||
-- 当前统一使用:
|
||||
-- root.contract -> 合同
|
||||
-- root.casefile -> 行政卷宗
|
||||
-- =========================================================
|
||||
WITH root_candidates AS (
|
||||
SELECT
|
||||
'root.contract'::varchar AS code,
|
||||
'合同'::varchar AS name,
|
||||
'合同业务大类'::text AS description,
|
||||
1::bigint AS entry_module_id,
|
||||
10::int AS sort_order
|
||||
UNION ALL
|
||||
SELECT
|
||||
'root.casefile'::varchar,
|
||||
'行政卷宗'::varchar,
|
||||
'行政卷宗业务大类'::text,
|
||||
2::bigint,
|
||||
20::int
|
||||
),
|
||||
upsert_roots AS (
|
||||
INSERT INTO leaudit_evaluation_point_groups (
|
||||
pid,
|
||||
code,
|
||||
name,
|
||||
description,
|
||||
document_type_id,
|
||||
entry_module_id,
|
||||
sort_order,
|
||||
is_enabled,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
0,
|
||||
rc.code,
|
||||
rc.name,
|
||||
rc.description,
|
||||
NULL,
|
||||
rc.entry_module_id,
|
||||
rc.sort_order,
|
||||
TRUE,
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM root_candidates rc
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM leaudit_evaluation_point_groups g
|
||||
WHERE g.deleted_at IS NULL
|
||||
AND COALESCE(g.pid, 0) = 0
|
||||
AND LOWER(g.code) = LOWER(rc.code)
|
||||
)
|
||||
RETURNING id, code
|
||||
)
|
||||
SELECT COUNT(*) AS inserted_root_count FROM upsert_roots;
|
||||
|
||||
UPDATE leaudit_evaluation_point_groups
|
||||
SET
|
||||
name = '合同',
|
||||
description = '合同业务大类',
|
||||
entry_module_id = 1,
|
||||
sort_order = 10,
|
||||
updated_at = NOW()
|
||||
WHERE deleted_at IS NULL
|
||||
AND COALESCE(pid, 0) = 0
|
||||
AND LOWER(code) = LOWER('root.contract');
|
||||
|
||||
UPDATE leaudit_evaluation_point_groups
|
||||
SET
|
||||
name = '行政卷宗',
|
||||
description = '行政卷宗业务大类',
|
||||
entry_module_id = 2,
|
||||
sort_order = 20,
|
||||
updated_at = NOW()
|
||||
WHERE deleted_at IS NULL
|
||||
AND COALESCE(pid, 0) = 0
|
||||
AND LOWER(code) = LOWER('root.casefile');
|
||||
|
||||
-- =========================================================
|
||||
-- 2. 优先把旧一级根直接下沉为目标二级分组
|
||||
-- 这样可复用现有 code,避免唯一索引冲突
|
||||
-- =========================================================
|
||||
WITH target_root_map AS (
|
||||
SELECT
|
||||
dt.id AS document_type_id,
|
||||
CASE
|
||||
WHEN dt.entry_module_id = 1 THEN (
|
||||
SELECT id FROM leaudit_evaluation_point_groups
|
||||
WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND code = 'root.contract'
|
||||
LIMIT 1
|
||||
)
|
||||
WHEN dt.entry_module_id = 2 THEN (
|
||||
SELECT id FROM leaudit_evaluation_point_groups
|
||||
WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND code = 'root.casefile'
|
||||
LIMIT 1
|
||||
)
|
||||
ELSE NULL
|
||||
END AS new_root_id
|
||||
FROM leaudit_document_types dt
|
||||
WHERE dt.deleted_at IS NULL
|
||||
),
|
||||
reparented_old_roots AS (
|
||||
UPDATE leaudit_evaluation_point_groups g
|
||||
SET
|
||||
pid = trm.new_root_id,
|
||||
entry_module_id = NULL,
|
||||
updated_at = NOW()
|
||||
FROM target_root_map trm
|
||||
WHERE g.deleted_at IS NULL
|
||||
AND COALESCE(g.pid, 0) = 0
|
||||
AND g.document_type_id = trm.document_type_id
|
||||
AND trm.new_root_id IS NOT NULL
|
||||
RETURNING g.id, g.document_type_id
|
||||
)
|
||||
SELECT COUNT(*) AS reparented_old_root_count FROM reparented_old_roots;
|
||||
|
||||
-- =========================================================
|
||||
-- 3. 如果某个文档类型没有旧一级根,再补建新的目标二级分组
|
||||
-- =========================================================
|
||||
WITH mapped_doc_types AS (
|
||||
SELECT
|
||||
dt.id AS document_type_id,
|
||||
dt.code AS document_type_code,
|
||||
dt.name AS document_type_name,
|
||||
dt.description,
|
||||
dt.entry_module_id,
|
||||
dt.sort_order,
|
||||
dt.is_enabled,
|
||||
CASE
|
||||
WHEN dt.entry_module_id = 1 THEN (
|
||||
SELECT id FROM leaudit_evaluation_point_groups
|
||||
WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND code = 'root.contract'
|
||||
LIMIT 1
|
||||
)
|
||||
WHEN dt.entry_module_id = 2 THEN (
|
||||
SELECT id FROM leaudit_evaluation_point_groups
|
||||
WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND code = 'root.casefile'
|
||||
LIMIT 1
|
||||
)
|
||||
ELSE NULL
|
||||
END AS root_group_id
|
||||
FROM leaudit_document_types dt
|
||||
WHERE dt.deleted_at IS NULL
|
||||
),
|
||||
insert_children AS (
|
||||
INSERT INTO leaudit_evaluation_point_groups (
|
||||
pid,
|
||||
code,
|
||||
name,
|
||||
description,
|
||||
document_type_id,
|
||||
entry_module_id,
|
||||
sort_order,
|
||||
is_enabled,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
m.root_group_id,
|
||||
m.document_type_code,
|
||||
m.document_type_name,
|
||||
COALESCE(m.description, m.document_type_name || '二级分组'),
|
||||
m.document_type_id,
|
||||
NULL,
|
||||
COALESCE(m.sort_order, 0),
|
||||
COALESCE(m.is_enabled, TRUE),
|
||||
NOW(),
|
||||
NOW()
|
||||
FROM mapped_doc_types m
|
||||
WHERE m.root_group_id IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM leaudit_evaluation_point_groups g
|
||||
JOIN leaudit_evaluation_point_groups root
|
||||
ON root.id = g.pid
|
||||
AND root.deleted_at IS NULL
|
||||
WHERE g.deleted_at IS NULL
|
||||
AND COALESCE(g.pid, 0) <> 0
|
||||
AND g.document_type_id = m.document_type_id
|
||||
AND root.document_type_id IS NULL
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM leaudit_evaluation_point_groups g
|
||||
WHERE g.deleted_at IS NULL
|
||||
AND LOWER(g.code) = LOWER(m.document_type_code)
|
||||
)
|
||||
RETURNING id, document_type_id
|
||||
)
|
||||
SELECT COUNT(*) AS inserted_child_count FROM insert_children;
|
||||
|
||||
-- =========================================================
|
||||
-- 4. 将旧一级根上的规则绑定迁到目标二级分组
|
||||
-- =========================================================
|
||||
WITH old_roots AS (
|
||||
SELECT id AS old_group_id, document_type_id
|
||||
FROM leaudit_evaluation_point_groups
|
||||
WHERE deleted_at IS NULL
|
||||
AND COALESCE(pid, 0) = 0
|
||||
AND document_type_id IS NOT NULL
|
||||
),
|
||||
target_children AS (
|
||||
SELECT child.id AS new_group_id, child.document_type_id
|
||||
FROM leaudit_evaluation_point_groups child
|
||||
JOIN leaudit_evaluation_point_groups root
|
||||
ON root.id = child.pid
|
||||
AND root.deleted_at IS NULL
|
||||
AND root.document_type_id IS NULL
|
||||
WHERE child.deleted_at IS NULL
|
||||
AND COALESCE(child.pid, 0) <> 0
|
||||
AND child.document_type_id IS NOT NULL
|
||||
),
|
||||
move_pairs AS (
|
||||
SELECT old_roots.old_group_id, target_children.new_group_id
|
||||
FROM old_roots
|
||||
JOIN target_children
|
||||
ON target_children.document_type_id = old_roots.document_type_id
|
||||
),
|
||||
updated_bindings AS (
|
||||
UPDATE leaudit_rule_group_bindings rgb
|
||||
SET group_id = mp.new_group_id,
|
||||
updated_at = NOW()
|
||||
FROM move_pairs mp
|
||||
WHERE rgb.group_id = mp.old_group_id
|
||||
AND rgb.deleted_at IS NULL
|
||||
RETURNING rgb.id
|
||||
)
|
||||
SELECT COUNT(*) AS moved_old_root_binding_count FROM updated_bindings;
|
||||
|
||||
-- =========================================================
|
||||
-- 5. 将旧默认子级上的规则绑定迁到目标二级分组
|
||||
-- 注意:只迁“父级仍是旧一级根”的默认子级
|
||||
-- =========================================================
|
||||
WITH old_default_children AS (
|
||||
SELECT
|
||||
child.id AS old_group_id,
|
||||
child.document_type_id
|
||||
FROM leaudit_evaluation_point_groups child
|
||||
JOIN leaudit_evaluation_point_groups parent
|
||||
ON parent.id = child.pid
|
||||
AND parent.deleted_at IS NULL
|
||||
WHERE child.deleted_at IS NULL
|
||||
AND COALESCE(child.pid, 0) <> 0
|
||||
AND parent.document_type_id IS NOT NULL
|
||||
AND (
|
||||
child.name = '通用'
|
||||
OR child.code LIKE '%.default'
|
||||
)
|
||||
),
|
||||
target_children AS (
|
||||
SELECT child.id AS new_group_id, child.document_type_id
|
||||
FROM leaudit_evaluation_point_groups child
|
||||
JOIN leaudit_evaluation_point_groups root
|
||||
ON root.id = child.pid
|
||||
AND root.deleted_at IS NULL
|
||||
AND root.document_type_id IS NULL
|
||||
WHERE child.deleted_at IS NULL
|
||||
AND COALESCE(child.pid, 0) <> 0
|
||||
AND child.document_type_id IS NOT NULL
|
||||
),
|
||||
move_pairs AS (
|
||||
SELECT old_default_children.old_group_id, target_children.new_group_id
|
||||
FROM old_default_children
|
||||
JOIN target_children
|
||||
ON target_children.document_type_id = old_default_children.document_type_id
|
||||
),
|
||||
updated_bindings AS (
|
||||
UPDATE leaudit_rule_group_bindings rgb
|
||||
SET group_id = mp.new_group_id,
|
||||
updated_at = NOW()
|
||||
FROM move_pairs mp
|
||||
WHERE rgb.group_id = mp.old_group_id
|
||||
AND rgb.deleted_at IS NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM leaudit_rule_group_bindings existing
|
||||
WHERE existing.deleted_at IS NULL
|
||||
AND existing.group_id = mp.new_group_id
|
||||
AND existing.rule_set_id = rgb.rule_set_id
|
||||
)
|
||||
RETURNING rgb.id
|
||||
),
|
||||
soft_deleted_duplicates AS (
|
||||
UPDATE leaudit_rule_group_bindings rgb
|
||||
SET deleted_at = NOW(),
|
||||
updated_at = NOW(),
|
||||
note = COALESCE(rgb.note, '') || ' [soft-deleted after business-root migration: duplicate with target child binding]'
|
||||
FROM move_pairs mp
|
||||
WHERE rgb.group_id = mp.old_group_id
|
||||
AND rgb.deleted_at IS NULL
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM leaudit_rule_group_bindings existing
|
||||
WHERE existing.deleted_at IS NULL
|
||||
AND existing.group_id = mp.new_group_id
|
||||
AND existing.rule_set_id = rgb.rule_set_id
|
||||
)
|
||||
RETURNING rgb.id
|
||||
)
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM updated_bindings) AS moved_default_child_binding_count,
|
||||
(SELECT COUNT(*) FROM soft_deleted_duplicates) AS soft_deleted_duplicate_default_binding_count;
|
||||
|
||||
-- =========================================================
|
||||
-- 6. 去重修复:避免迁移后同一二级分组重复绑定同一规则集
|
||||
-- 保留 priority 更高、id 更小的一条
|
||||
-- =========================================================
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
id,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY group_id, rule_set_id
|
||||
ORDER BY priority DESC, id ASC
|
||||
) AS rn
|
||||
FROM leaudit_rule_group_bindings
|
||||
WHERE deleted_at IS NULL
|
||||
),
|
||||
soft_deleted AS (
|
||||
UPDATE leaudit_rule_group_bindings rgb
|
||||
SET deleted_at = NOW(),
|
||||
updated_at = NOW()
|
||||
FROM ranked r
|
||||
WHERE rgb.id = r.id
|
||||
AND r.rn > 1
|
||||
RETURNING rgb.id
|
||||
)
|
||||
SELECT COUNT(*) AS deduped_binding_count FROM soft_deleted;
|
||||
|
||||
-- =========================================================
|
||||
-- 7. 清理迁移后已空置的旧默认子级
|
||||
-- 条件:
|
||||
-- - 自身无有效规则绑定
|
||||
-- - 自身是“通用 / *.default”
|
||||
-- - 父级已是具体业务类型节点
|
||||
-- =========================================================
|
||||
WITH empty_default_children AS (
|
||||
SELECT child.id
|
||||
FROM leaudit_evaluation_point_groups child
|
||||
JOIN leaudit_evaluation_point_groups parent
|
||||
ON parent.id = child.pid
|
||||
AND parent.deleted_at IS NULL
|
||||
LEFT JOIN leaudit_rule_group_bindings rgb
|
||||
ON rgb.group_id = child.id
|
||||
AND rgb.deleted_at IS NULL
|
||||
WHERE child.deleted_at IS NULL
|
||||
AND COALESCE(child.pid, 0) <> 0
|
||||
AND parent.document_type_id IS NOT NULL
|
||||
AND (
|
||||
child.name = '通用'
|
||||
OR child.code LIKE '%.default'
|
||||
)
|
||||
GROUP BY child.id
|
||||
HAVING COUNT(rgb.id) = 0
|
||||
),
|
||||
soft_deleted_groups AS (
|
||||
UPDATE leaudit_evaluation_point_groups g
|
||||
SET deleted_at = NOW(),
|
||||
updated_at = NOW()
|
||||
FROM empty_default_children edc
|
||||
WHERE g.id = edc.id
|
||||
RETURNING g.id
|
||||
)
|
||||
SELECT COUNT(*) AS soft_deleted_empty_default_group_count FROM soft_deleted_groups;
|
||||
|
||||
-- =========================================================
|
||||
-- 8. 重建文档类型汇总绑定表
|
||||
-- =========================================================
|
||||
UPDATE leaudit_rule_type_bindings
|
||||
SET deleted_at = NOW(),
|
||||
updated_at = NOW()
|
||||
WHERE deleted_at IS NULL;
|
||||
|
||||
INSERT INTO leaudit_rule_type_bindings (
|
||||
doc_type_id,
|
||||
doc_type_code,
|
||||
rule_set_id,
|
||||
binding_mode,
|
||||
priority,
|
||||
is_active,
|
||||
note,
|
||||
created_at,
|
||||
updated_at,
|
||||
region
|
||||
)
|
||||
SELECT DISTINCT ON (child.document_type_id, rgb.rule_set_id)
|
||||
child.document_type_id,
|
||||
dt.code,
|
||||
rgb.rule_set_id,
|
||||
'explicit',
|
||||
100,
|
||||
TRUE,
|
||||
're-built from second-level group bindings after business-root migration',
|
||||
NOW(),
|
||||
NOW(),
|
||||
'default'
|
||||
FROM leaudit_rule_group_bindings rgb
|
||||
JOIN leaudit_evaluation_point_groups child
|
||||
ON child.id = rgb.group_id
|
||||
AND child.deleted_at IS NULL
|
||||
AND COALESCE(child.pid, 0) <> 0
|
||||
JOIN leaudit_evaluation_point_groups root
|
||||
ON root.id = child.pid
|
||||
AND root.deleted_at IS NULL
|
||||
AND root.document_type_id IS NULL
|
||||
JOIN leaudit_document_types dt
|
||||
ON dt.id = child.document_type_id
|
||||
WHERE rgb.deleted_at IS NULL
|
||||
AND rgb.is_active = TRUE
|
||||
ORDER BY child.document_type_id, rgb.rule_set_id, rgb.priority DESC, rgb.id ASC;
|
||||
|
||||
-- =========================================================
|
||||
-- 9. 迁移后输出检查摘要
|
||||
-- =========================================================
|
||||
SELECT
|
||||
root.code AS root_code,
|
||||
root.name AS root_name,
|
||||
root.entry_module_id,
|
||||
COUNT(child.id) AS child_count
|
||||
FROM leaudit_evaluation_point_groups root
|
||||
LEFT JOIN leaudit_evaluation_point_groups child
|
||||
ON child.pid = root.id
|
||||
AND child.deleted_at IS NULL
|
||||
WHERE root.deleted_at IS NULL
|
||||
AND COALESCE(root.pid, 0) = 0
|
||||
AND root.document_type_id IS NULL
|
||||
GROUP BY root.id, root.code, root.name, root.entry_module_id
|
||||
ORDER BY root.sort_order, root.id;
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user