# 评查点分组迁移执行前检查清单 更新时间:2026-05-03 ## 1. 目标 本清单用于在正式执行 `scripts/创建sql/migrate_rule_groups_to_doc_type_roots.sql` 之前,先把当前库里的旧数据、兼容态数据和潜在冲突点查清楚。 如果希望直接执行一份只读巡检 SQL,可使用: - `scripts/创建sql/precheck_rule_group_migration.sql` 本次迁移的目标仍然是: - 一级分组 = 业务大类 - 二级分组 = 具体业务类型 - 规则集 = 挂在二级分组下 - 入口模块 = 绑定一级分组 ## 2. 当前风险结论 正式迁移前,必须先确认下面 4 类风险: 1. 是否仍存在“一级直接挂具体文档类型”的旧根数据。 2. 是否存在同一个 `document_type_id` 被多个二级分组同时承接的情况。 3. 是否存在规则集同时挂在旧一级根和旧默认子级上,导致迁移后重复。 4. `document_types.entry_module_id` 是否足够可靠,能支撑“先按入口模块粗分到一级业务大类”。 如果这 4 类风险没有检查清楚,不应直接跑迁移脚本。 ## 2.1 当前已知巡检结论(2026-05-03) 基于本次实际巡检结果: - `leaudit_document_types` 共 20 条,入口归属完整 - 合同管理:10 条 - 案卷智能评查:10 条 - 当前仍有 20 个旧一级根 - 即:`一级 = 具体文档类型` - 当前已经存在 2 个新一级业务大类根 - `root.contract -> 合同` - `root.casefile -> 行政卷宗` - 当前有 20 个默认二级分组 - 即:`二级 = 通用 / *.default` - 当前没有发现明显冲突: - 没有“同一文档类型被多个二级分组重复承接” - 没有“同一规则集同时挂在旧一级根和默认子级” - 没有“二级分组未绑定规则集” 结论: - 当前库已经具备正式迁移的基础条件 - 但还没有完成最后的结构补齐 - 正式迁移前仍要先补 `entry_module_id`,再重跑巡检 ## 3. 必查项 ### 3.1 一级旧根检查 确认当前是否还有“一级 = 具体文档类型”的历史根: ```sql SELECT id, code, name, document_type_id, entry_module_id, sort_order, is_enabled FROM leaudit_evaluation_point_groups WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND document_type_id IS NOT NULL ORDER BY id; ``` 判定原则: - 查出来的这些记录,都属于兼容态旧根。 - 正式迁移后,它们不应再继续作为最终一级分组存在。 ### 3.2 一级业务大类根检查 确认当前是否已经存在真正的业务大类根: ```sql SELECT id, code, name, entry_module_id, sort_order, is_enabled FROM leaudit_evaluation_point_groups WHERE deleted_at IS NULL AND COALESCE(pid, 0) = 0 AND document_type_id IS NULL ORDER BY sort_order, id; ``` 判定原则: - 正常目标结构下,这里应该看到如 `合同`、`卷宗` 这类一级业务大类。 - 如果这里为空,说明当前库还没有真正切到目标结构。 ### 3.3 二级分组唯一性检查 确认同一个文档类型是否被多个二级分组重复承接: ```sql SELECT document_type_id, COUNT(*) AS child_count, STRING_AGG(name, ' / ' ORDER BY id) AS child_names FROM leaudit_evaluation_point_groups WHERE deleted_at IS NULL AND COALESCE(pid, 0) <> 0 AND document_type_id IS NOT NULL GROUP BY document_type_id HAVING COUNT(*) > 1 ORDER BY document_type_id; ``` 判定原则: - 如果结果为空,说明每个文档类型目前最多只挂到一个二级分组,迁移最安全。 - 如果结果不为空,要逐条判断: - 是合理的“一个文档类型拆成多个业务子类型” - 还是历史脏数据 ### 3.4 旧默认子级检查 确认当前是否存在旧默认子级: ```sql SELECT child.id, child.pid, parent.name AS parent_name, child.name, child.code, 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 ( child.name = '通用' OR child.code LIKE '%.default' ) ORDER BY child.id; ``` 判定原则: - 这些记录多数是旧链路下的“默认子类型”兼容数据。 - 迁移时如果它们已经被真实二级业务类型替代,应考虑把规则集迁走后再停用或清理。 ### 3.5 规则集重复挂载检查 确认同一个文档类型下,旧一级根和默认子级是否同时挂了相同规则集: ```sql WITH target_groups AS ( SELECT g.id, g.document_type_id, g.name, g.code, CASE WHEN COALESCE(g.pid, 0) = 0 THEN 'old_root' WHEN g.name = '通用' OR g.code LIKE '%.default' THEN 'default_child' ELSE 'other_child' END AS group_kind FROM leaudit_evaluation_point_groups g WHERE g.deleted_at IS NULL AND g.document_type_id IS NOT NULL ) SELECT tg.document_type_id, rgb.rule_set_id, COUNT(*) AS binding_count, STRING_AGG(tg.group_kind || ':' || tg.name, ' / ' ORDER BY tg.id) AS group_sources FROM leaudit_rule_group_bindings rgb JOIN target_groups tg ON tg.id = rgb.group_id WHERE rgb.deleted_at IS NULL GROUP BY tg.document_type_id, rgb.rule_set_id HAVING COUNT(*) > 1 ORDER BY tg.document_type_id, rgb.rule_set_id; ``` 判定原则: - 如果结果不为空,迁移脚本执行前要先确认是否允许去重。 - 否则迁移后可能出现: - 同一规则集被重复搬到新二级分组 - 或者旧运行汇总结果不稳定 ### 3.6 文档类型与入口模块映射检查 确认 `document_types` 是否都有稳定入口归属: ```sql SELECT dt.id, dt.code, dt.name, dt.entry_module_id, em.name AS entry_module_name FROM leaudit_document_types dt LEFT JOIN leaudit_entry_modules em ON em.id = dt.entry_module_id WHERE dt.deleted_at IS NULL ORDER BY dt.id; ``` 重点看: - 是否存在 `entry_module_id IS NULL` - 是否存在入口模块已被删除、停用或名称异常 - 是否存在“明明是合同类型却挂在卷宗入口”这类错误归属 ### 3.7 规则集可运行性检查 迁移前需要确认二级分组绑定过去的规则集不是空壳: ```sql SELECT rs.id, rs.rule_name, rs.rule_type, rs.current_version_id, rs.fallback_version_id FROM leaudit_rule_sets rs WHERE rs.deleted_at IS NULL ORDER BY rs.id; ``` 这一步建议再配合业务接口实际看: - 是否有可用版本 ## 4. 正式迁移推荐执行顺序 ### 步骤 1:先备份 必须先备份这几张表: - `leaudit_evaluation_point_groups` - `leaudit_rule_group_bindings` - `leaudit_rule_type_bindings` - `leaudit_document_types` ### 步骤 2:先补字段,不迁数据 先补结构层缺口: 1. 给 `leaudit_evaluation_point_groups` 增加 `entry_module_id` 2. 建索引 3. 给已有一级业务大类根补入口绑定 建议值: - `root.contract -> entry_module_id = 1` - `root.casefile -> entry_module_id = 2` ### 步骤 3:重新跑巡检 字段补完后,重新执行: - `scripts/创建sql/precheck_rule_group_migration.sql` 确认: - 一级业务大类根能正确看到入口模块字段 - 巡检结果仍无重复承接、重复绑定、空壳规则集等问题 ### 步骤 4:测试库执行正式迁移 再执行: - `scripts/创建sql/migrate_rule_groups_to_business_roots.sql` 说明: - 旧脚本 `scripts/创建sql/migrate_rule_groups_to_doc_type_roots.sql` 仅保留兼容历史引用 - 不建议继续作为正式迁移脚本使用 ### 步骤 5:迁后验证 4 个页面 必须验证: 1. `/rule-groups` 2. `/files/upload` 3. `/document-types/new?id=...` 4. `/documents/list` ## 5. 迁移脚本调整口径 基于当前巡检结果,正式脚本建议继续遵守: 1. 不要再硬编码“只有合同和卷宗” 2. 优先复用已存在业务大类根,不重复新造 3. 一级根编码必须统一,例如继续沿用: - `root.contract` - `root.casefile` - 可用规则数是否大于 0 否则迁完结构后,上传仍然会失败,只是失败原因从“结构问题”变成“规则集不可运行”。 ## 4. 执行前必须人工确认的业务映射 SQL 只能粗分,业务归属必须人工确认: ### 4.1 一级业务大类清单 至少要先列清: - 哪些文档类型归到 `合同` - 哪些文档类型归到 `卷宗` - 是否已经存在第 3 个业务大类,如 `内部公文` ### 4.2 二级业务类型命名规范 要确认: - 二级显示名称是否直接用 `document_types.name` - 还是需要改成更贴近业务的名称 - 例如:`处罚-一般程序` - 而不是数据库里原始的技术名 ### 4.3 默认子类型保留策略 需要人工确认: - 哪些文档类型仍保留 `默认子类型(通用)` - 哪些必须拆成多个真实二级业务类型 ## 5. 执行顺序建议 推荐按下面顺序推进: 1. 跑本清单中的查询 SQL,导出当前状态。 2. 形成一份 `document_type -> 一级业务大类 -> 目标二级名称` 的确认表。 3. 在测试库执行迁移脚本。 4. 验证以下页面: - `/rule-groups` - `/files/upload` - `/document-types/new?id=...` - `/documents/list` 5. 验证上传链路: - 能否正确选择子类型 - 上传后是否命中预期规则集 - 合同附件追加链路是否仍正常 6. 测试通过后,再评估正式库执行窗口。 ## 6. 当前不建议直接执行的情况 只要出现以下任一情况,都不建议直接执行迁移脚本: - `document_types.entry_module_id` 还有大量空值 - 同一文档类型被多个旧组重复承接,但业务还没定论 - 规则集存在大量“可用规则数 = 0” - 一级业务大类并不只有 `合同 / 卷宗`,但映射方案还没补 - 业务方还没确认二级命名与保留策略 ## 7. 当前结论 截至当前,这套系统已经具备: - 前端按新链路展示和解释的能力 - 后端兼容新旧结构的能力 - 新配置回写旧运行绑定表的能力 但数据库正式迁移这一步,仍然必须先做“数据盘点 + 业务确认 + 测试库演练”三件事,不能直接在正式库硬切。