463 lines
15 KiB
PL/PgSQL
463 lines
15 KiB
PL/PgSQL
-- 评查点分组正式迁移脚本(业务大类根版本)
|
|
-- 目标:
|
|
-- 一级分组 = 业务大类(合同 / 行政卷宗 / 后续新增业务)
|
|
-- 二级分组 = 具体业务类型
|
|
-- 规则集 = 挂在二级分组下
|
|
-- 入口模块 = 绑定一级分组
|
|
--
|
|
-- 重要说明:
|
|
-- 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;
|