-- 修复入口模块归属历史数据 -- 执行目标: -- 1. 回填可通过业务类型/规则分组明确推导的 leaudit_documents.entry_module_id。 -- 2. 回填可通过子业务类型明确推导的一级/二级业务分组 entry_module_id。 -- 3. 软删除无文档、无规则绑定的 Playwright/test 残留规则分组。 -- 4. 补齐正式案卷入口的默认功能菜单。 -- -- 安全边界: -- 1. 不处理无法推导的旧公文示例。 -- 2. 不把数据强行塞到 entry_module_id=1。 -- 3. 不物理删除数据,只做软删除或确定性回填。 BEGIN; -- 1. 回填历史文档 entry_module_id:只处理能推导到“未删除入口模块”的文档。 WITH resolved_documents AS ( SELECT d.id, COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) AS resolved_entry_module_id FROM leaudit_documents d LEFT JOIN leaudit_document_types dt ON dt.id = d.type_id LEFT JOIN leaudit_evaluation_point_groups g ON g.id = d.group_id LEFT JOIN leaudit_evaluation_point_groups parent ON parent.id = g.pid JOIN leaudit_entry_modules em ON em.id = COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) AND em.deleted_at IS NULL WHERE d.deleted_at IS NULL AND d.entry_module_id IS NULL AND COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) IS NOT NULL ) UPDATE leaudit_documents d SET entry_module_id = rd.resolved_entry_module_id, updated_at = NOW() FROM resolved_documents rd WHERE d.id = rd.id; -- 2. 回填一级业务大类 entry_module_id:只处理所有子业务类型都指向同一个未删除入口模块的一级分组。 WITH resolvable_roots AS ( SELECT root.id AS root_id, MIN(child_dt.entry_module_id) AS resolved_entry_module_id FROM leaudit_evaluation_point_groups root JOIN leaudit_evaluation_point_groups child ON child.pid = root.id AND child.deleted_at IS NULL JOIN leaudit_document_types child_dt ON child_dt.id = child.document_type_id AND child_dt.deleted_at IS NULL JOIN leaudit_entry_modules em ON em.id = child_dt.entry_module_id AND em.deleted_at IS NULL WHERE root.deleted_at IS NULL AND COALESCE(root.pid, 0) = 0 AND root.entry_module_id IS NULL GROUP BY root.id HAVING COUNT(DISTINCT child_dt.entry_module_id) = 1 ) UPDATE leaudit_evaluation_point_groups root SET entry_module_id = rr.resolved_entry_module_id, updated_at = NOW() FROM resolvable_roots rr WHERE root.id = rr.root_id; -- 3. 二级业务类型继承父级入口模块:只处理父级已明确归属、子级为空的记录。 UPDATE leaudit_evaluation_point_groups child SET entry_module_id = parent.entry_module_id, updated_at = NOW() FROM leaudit_evaluation_point_groups parent WHERE child.deleted_at IS NULL AND parent.deleted_at IS NULL AND child.pid = parent.id AND COALESCE(parent.pid, 0) = 0 AND parent.entry_module_id IS NOT NULL AND child.entry_module_id IS NULL; -- 4. 软删除无引用的测试残留规则分组。 WITH candidate_groups AS ( SELECT g.id FROM leaudit_evaluation_point_groups g WHERE g.deleted_at IS NULL AND ( g.code = 'testmzceshi' OR g.code LIKE 'pw.%' ) ), safe_groups AS ( SELECT cg.id FROM candidate_groups cg WHERE NOT EXISTS ( SELECT 1 FROM leaudit_documents d WHERE d.deleted_at IS NULL AND d.group_id = cg.id ) AND NOT EXISTS ( SELECT 1 FROM leaudit_rule_group_bindings b WHERE b.deleted_at IS NULL AND b.group_id = cg.id ) AND NOT EXISTS ( SELECT 1 FROM leaudit_evaluation_point_groups child JOIN leaudit_documents d ON d.group_id = child.id AND d.deleted_at IS NULL WHERE child.deleted_at IS NULL AND child.pid = cg.id ) AND NOT EXISTS ( SELECT 1 FROM leaudit_evaluation_point_groups child JOIN leaudit_rule_group_bindings b ON b.group_id = child.id AND b.deleted_at IS NULL WHERE child.deleted_at IS NULL AND child.pid = cg.id ) ) UPDATE leaudit_evaluation_point_groups g SET deleted_at = NOW(), updated_at = NOW() FROM safe_groups sg WHERE g.id = sg.id; -- 5. 补齐案卷智能评查的通用文档评查功能菜单。 UPDATE leaudit_entry_modules SET features = '["home", "documents", "upload", "rules", "rule_groups"]'::jsonb, updated_at = NOW() WHERE deleted_at IS NULL AND id = 2 AND name = '案卷智能评查' AND ( features IS NULL OR jsonb_typeof(features) <> 'array' OR jsonb_array_length(features) = 0 ); COMMIT; -- 执行后建议立即运行: -- psql "$DATABASE_URL" -f scripts/创建sql/verify_entry_module_menu_profile.sql