From 68d0b4c8785b7e06dfd0efee8bc9a4b0e5a39e4d Mon Sep 17 00:00:00 2001 From: wren <“porlong@qq.com”> Date: Mon, 25 May 2026 09:50:01 +0800 Subject: [PATCH] feat: update audit platform workspace --- .tmp-rules-1-0.yaml | 2898 +++++++++++++++++ 387f06411f279cd1d2ea98aacc5a6c1f.png | Bin 0 -> 529016 bytes app.toml | 11 + .../review-side-drawer-preview.html | 971 ++++++ .../plans/2026-05-22-rag-dsl-bridge-merge.md | 407 +++ .../2026-05-22-route-permission-guard.md | 171 + ...26-05-23-business-entry-ux-optimization.md | 652 ++++ ...odule-menu-profile-multitenant-refactor.md | 2224 +++++++++++++ ...23-entry-module-phase2-scope-completion.md | 248 ++ .../plans/2026-05-23-qichacha-migration.md | 71 + ...rule-editor-smoke-cleanup-20260521-225643.json | 128 + .../rule-domain-before-reset-20260521-221930.sql | 527 +++ .../rule-domain-before-reset-20260521-221940.sql | 527 +++ fastapi_admin/config/__init__.py | 4 +- fastapi_admin/config/_settings.py | 25 + .../exception/QichachaException.py | 7 + .../controllers/crossReviewController.py | 4 +- .../controllers/documentController.py | 35 +- .../controllers/evaluationPointController.py | 169 +- .../evaluationPointGroupController.py | 6 +- .../controllers/govdocController.py | 25 + .../controllers/homeController.py | 25 +- .../controllers/qichachaController.py | 99 + .../controllers/usageStatsController.py | 22 + .../domian/Dto/entryModuleDto.py | 4 + .../fastapi_leaudit/domian/Dto/qichachaDto.py | 17 + .../domian/vo/crossReviewVo.py | 8 +- .../fastapi_leaudit/domian/vo/documentVo.py | 2 + .../domian/vo/entryModuleAdminVo.py | 11 + .../fastapi_leaudit/domian/vo/homeVo.py | 22 + .../fastapi_leaudit/domian/vo/qichachaVo.py | 55 + .../fastapi_leaudit/models/__init__.py | 2 + .../models/qichachaCompanyInfo.py | 84 + .../fastapi_leaudit/services/__init__.py | 2 + .../services/crossReviewService.py | 7 +- .../services/documentService.py | 5 + .../services/evaluationPointGroupService.py | 9 +- .../fastapi_leaudit/services/govdocService.py | 3 + .../fastapi_leaudit/services/homeService.py | 13 +- .../services/impl/crossReviewServiceImpl.py | 146 +- .../services/impl/documentServiceImpl.py | 239 +- .../impl/entryModuleAdminServiceImpl.py | 252 +- .../impl/evaluationPointGroupServiceImpl.py | 80 +- .../services/impl/govdocServiceImpl.py | 24 +- .../services/impl/homeServiceImpl.py | 193 +- .../services/impl/qichachaClient.py | 119 + .../services/impl/qichachaServiceImpl.py | 174 + .../services/impl/qichachaVoAssembler.py | 40 + .../services/impl/rbacAdminServiceImpl.py | 113 +- .../services/impl/rbacServiceImpl.py | 187 +- .../services/impl/ruleServiceImpl.py | 34 +- .../services/impl/usageStatsServiceImpl.py | 4 +- .../services/qichachaService.py | 40 + legal-platform-frontend | 2 +- .../entry_module_menu_profile_migration.sql | 67 + .../rbac_entry_module_super_admin_only.sql | 66 + .../repair_entry_module_scope_data_20260524.sql | 145 + ...pair_govdoc_sample_entry_module_20260524.sql | 15 + .../创建sql/schema_qichacha_company_info.sql | 36 + scripts/创建sql/seed_govdoc_entry_module.sql | 4 +- scripts/创建sql/seed_govdoc_routes.sql | 22 +- scripts/创建sql/user_rbac_seed.sql | 29 +- .../verify_entry_module_menu_profile.sql | 209 ++ test-results/.last-run.json | 4 + ...right-entry-module-remaining-acceptance.js | 167 + .../test_cross_review_progress_permission.py | 55 + tests/test_govdoc_permissions.py | 128 + tests/test_home_dashboard_statistics.py | 73 + tests/test_qichacha_config_client.py | 66 + tests/test_qichacha_service.py | 194 ++ ...st_review_document_payload_page_quality.py | 96 + tests/test_rule_write_scope.py | 23 + .../test_usage_stats_role_permission_scope.py | 17 + 73 files changed, 12196 insertions(+), 367 deletions(-) create mode 100644 .tmp-rules-1-0.yaml create mode 100644 387f06411f279cd1d2ea98aacc5a6c1f.png create mode 100644 docs/prototypes/review-side-drawer-preview.html create mode 100644 docs/superpowers/plans/2026-05-22-rag-dsl-bridge-merge.md create mode 100644 docs/superpowers/plans/2026-05-22-route-permission-guard.md create mode 100644 docs/superpowers/plans/2026-05-23-business-entry-ux-optimization.md create mode 100644 docs/superpowers/plans/2026-05-23-entry-module-menu-profile-multitenant-refactor.md create mode 100644 docs/superpowers/plans/2026-05-23-entry-module-phase2-scope-completion.md create mode 100644 docs/superpowers/plans/2026-05-23-qichacha-migration.md create mode 100644 docs/规则编辑/backups/frontend-rule-editor-smoke-cleanup-20260521-225643.json create mode 100644 docs/规则编辑/backups/rule-domain-before-reset-20260521-221930.sql create mode 100644 docs/规则编辑/backups/rule-domain-before-reset-20260521-221940.sql create mode 100644 fastapi_common/fastapi_common_web/exception/QichachaException.py create mode 100644 fastapi_modules/fastapi_leaudit/controllers/qichachaController.py create mode 100644 fastapi_modules/fastapi_leaudit/domian/Dto/qichachaDto.py create mode 100644 fastapi_modules/fastapi_leaudit/domian/vo/qichachaVo.py create mode 100644 fastapi_modules/fastapi_leaudit/models/qichachaCompanyInfo.py create mode 100644 fastapi_modules/fastapi_leaudit/services/impl/qichachaClient.py create mode 100644 fastapi_modules/fastapi_leaudit/services/impl/qichachaServiceImpl.py create mode 100644 fastapi_modules/fastapi_leaudit/services/impl/qichachaVoAssembler.py create mode 100644 fastapi_modules/fastapi_leaudit/services/qichachaService.py create mode 100644 scripts/创建sql/entry_module_menu_profile_migration.sql create mode 100644 scripts/创建sql/rbac_entry_module_super_admin_only.sql create mode 100644 scripts/创建sql/repair_entry_module_scope_data_20260524.sql create mode 100644 scripts/创建sql/repair_govdoc_sample_entry_module_20260524.sql create mode 100644 scripts/创建sql/schema_qichacha_company_info.sql create mode 100644 scripts/创建sql/verify_entry_module_menu_profile.sql create mode 100644 test-results/.last-run.json create mode 100644 test-results/leaudit-playwright-entry-module-remaining-acceptance.js create mode 100644 tests/test_cross_review_progress_permission.py create mode 100644 tests/test_govdoc_permissions.py create mode 100644 tests/test_home_dashboard_statistics.py create mode 100644 tests/test_qichacha_config_client.py create mode 100644 tests/test_qichacha_service.py create mode 100644 tests/test_review_document_payload_page_quality.py create mode 100644 tests/test_usage_stats_role_permission_scope.py diff --git a/.tmp-rules-1-0.yaml b/.tmp-rules-1-0.yaml new file mode 100644 index 0000000..cf5a576 --- /dev/null +++ b/.tmp-rules-1-0.yaml @@ -0,0 +1,2898 @@ +metadata: + type_id: 行政卷宗.行政处罚 + name: 烟草专卖行政处罚卷宗 + version: '1.0' + last_updated: '2026-04-18' + parent: 行政卷宗 + inherits_from: + - base.common + - base.administrative_case + classification_keywords: + - 行政处罚 + - 烟草专卖 + - 处罚决定书 + - 立案报告 + - 询问笔录 + description: '烟草专卖行政处罚卷宗审核。 + + 覆盖:立案、现场检查、证据先行登记保存、取证核价、询问笔录、权利告知、 + + 调查终结、处理审批、事先告知、处罚决定、送达、执行、结案全流程。 + + ' + # 开 medium 风险规则的 LLM 救援(跨子文档对齐失败交给 rescue 模块 + # 的 L1 判定语义等价,如"投诉举报" vs "举报")。 + rescue_profile: + rescue_risk: [medium] + +# TOC 页定位(dossier_segmenter 使用) +# keywords: 本类卷宗的目录标题(OCR 空白自动规整,"卷 宗 目 录" 也命中) +# anti_keywords: 卷内"内部目录",避免被误判为卷宗级 TOC +# 两个列表均为"扩展默认值",下面显式列出本类卷宗实际会遇到的项 —— +# 默认的 卷宗目录 / 卷内目录 / Contents 等仍自动生效。 +toc: + keywords: + # 实际 OCR 观察到的目录标题(均为 defaults 一部分,显式列出作自注释) + - 卷宗目录 + - 卷内目录 + anti_keywords: + # 卷内子文档自带的"目录"标题,不是卷宗级 TOC —— 必须排除 + - 证据材料目录 # 重大执法行为法制审核送审表 里的证据清单 + - 物品目录 # 抽样取证物品清单等 + +# 跨子文档派生字段 —— 给规则里的 `activate_if` / 对级 `when` 用 +derived_fields: + # 当事人类型:决定一条规则里"个人字段 pair"还是"单位字段 pair"该不该对齐 + # + # 按 USCC 第 2 位判定(GB 32100-2015 法人和其他组织统一社会信用代码): + # 1 = 机关 → 单位 + # 2 = 个体工商户 → 个人(法律归类:自然人工商业) + # 3 = 农民专业合作社 → 单位 + # 4 = 事业单位 → 单位 + # 5 = 企业 → 单位 + # 8 = 社团 → 单位 + # 9 = 其他组织 → 单位 + # + # 个体户虽然有 USCC 和营业执照,但当事人栏填个人信息(姓名/身份证), + # 所以单位 pair 应跳过;执照字段作为辅助证据另行处理。 + # + # 注:不看"字号"——当前 OCR 常把案件文号误抽到 字号 字段; + # 执照名称/执照统一社会信用代码 在个体户里也存在,因此不作为单位标志。 + # 表达式必须单行(evaluate 不支持多行条件)。 + - name: 当事人类型 + type: string + # 嵌套 IfExp 走短路(BoolOp 求值所有分支,`not None` 会走 null-propagation + # 返回 None 而被 IfExp 当 False 走到 else,导致对 None 调 .startswith 崩溃) + # - USCC 空/缺失 → 个人 + # - USCC 以 '92' 开头 → 个人(个体工商户) + # - 其它 (91/93/94/95/… 开头) → 单位 + compute: "'个人' if 处罚决定书.统一社会信用代码 == None else ('个人' if 处罚决定书.统一社会信用代码.startswith('92') else '单位')" + desc: 案件当事人类型(个人 / 单位)—— 按 USCC 第 2 位判,个体户 (92xxx) 判为个人 + + # 证据复制(提取)单可能同时存在多张居民身份证(当事人、举报人、 + # 未成年人、相关人等)。抽取侧把整组居民身份证记录按 multi_entity 抽 + # 下来,由这里挑出归属当事人的那一份;规则再用 + # `证据复制(提取)单当事人.身份证*` 对齐处罚决定书/审批表/终结报告。 + # 只有一张身份证时引擎自动短路,不计 LLM 调用。 + - name: 证据复制(提取)单当事人 + type: object + compute_by: llm + prompt: |- + 以下是证据复制(提取)单中全部居民身份证记录: + + {居民身份证} + + 当事人姓名:{处罚决定书.当事人} + 当事人身份证号:{处罚决定书.身份证号码} + + 请挑出归属「当事人本人」(被处罚对象)的那一份身份证,按原字段 + 结构返回一个 JSON 对象(严格包含 身份证姓名/身份证性别/身份证民族/ + 身份证住址/身份证号/身份证背面,空值写 null)。 + + 优先以身份证号匹配当事人身份证号;若号码缺失,用姓名匹配。匹配不到 + 或无法判断归属时返回 JSON null。除该 JSON 外不要输出任何解释文字。 + depends_on: + - 居民身份证 + - 处罚决定书.当事人 + - 处罚决定书.身份证号码 + + # 询问笔录可能包含多份笔录记录(同一卷宗针对多人询问)。抽取侧把所 + # 有被询问人按 multi_entity 抽下来,由这里挑当事人那份;规则再用 + # `询问笔录当事人.被询问人*` 做一致性校验。只有一份被询问人记录时 + # 引擎自动短路,不计 LLM 调用。 + - name: 询问笔录当事人 + type: object + compute_by: llm + prompt: |- + 以下是询问笔录中全部「被询问人」记录: + + {被询问人} + + 当事人姓名:{处罚决定书.当事人} + 当事人身份证号(若有):{处罚决定书.身份证号码} + + 请挑出归属「当事人本人」(被处罚对象)的那一份笔录记录,按原字段 + 结构返回一个 JSON 对象(严格包含 被询问人姓名/被询问人性别/被询问人民族/ + 被询问人证件/被询问人电话/被询问人住址/被询问人经营地址,空值写 null)。 + + 优先以证件号匹配当事人身份证号;若号码缺失,用姓名匹配。匹配不到 + 或无法判断归属时返回 JSON null。除该 JSON 外不要输出任何解释文字。 + depends_on: + - 被询问人 + - 处罚决定书.当事人 + - 处罚决定书.身份证号码 + +sub_documents: +- id: 先行登记保存证据处理通知书 + name: 先行登记保存证据处理通知书 + required: false + classifier: + title_patterns: + - 先行登记保存证据处理通知书 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 处理方式 + type: verbatim + vlm_extract_mode: always + desc: 证据做出如下处理→选中的选项,要看打勾的选项 +- id: 卷内备考表 + name: 卷内备考表 + required: true + classifier: + title_patterns: + - 卷内备考表 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 立卷时间 + type: verbatim + desc: 立卷时间 +- id: 卷宗封面 + name: 卷宗封面 + required: false + classifier: + title_patterns: + - ^##?\s*卷\s*宗\s*$ + keywords: + - 此卷共计 + - 归档日期 + - 保存期限 + min_score: 1.0 + extract: + - group: 基本信息 + fields: + - name: 处理结果 + type: string + desc: 处理结果 +- id: 处罚决定书 + name: 处罚决定书 + required: true + classifier: + title_patterns: + - 处罚决定书 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 字号 + type: verbatim + desc: 字号 + - name: 当事人 + type: verbatim + desc: 当事人 + - name: 性别 + type: enum + allowed: + - 男 + - 女 + desc: 性别 + - name: 民族 + type: verbatim + desc: 民族 + - name: 烟草专卖许可证号 + type: verbatim + desc: 烟草专卖许可证号 + - name: 经营地址 + type: string + desc: 经营地址 + - name: 统一社会信用代码 + type: uscc + desc: 统一社会信用代码 + - name: 落款日期 + type: date + desc: 落款日期 + - name: 身份证住址 + type: string + desc: 身份证住址 + - name: 身份证号码 + type: chinese-id + desc: 身份证号码 + - group: 罚款信息 + fields: + - name: 罚款项目 + type: string + desc: 正文→罚款项目 + - name: 罚款基数 + type: money + desc: 正文→罚款项目金额基数 + - name: 罚款比例 + type: string + desc: 正文→罚款百分比 保留原格式如"50%" + - name: 罚款总额 + type: money + desc: 正文→罚款总金额 + - name: 罚款说明 + type: string + desc: 正文→罚款说明 + - name: 证据列举 + type: string + desc: 正文→证据列举 + - group: 权利告知 + fields: + - name: 救济途径 + type: string + desc: 正文→救济途径 +- id: 抽样取证物品清单 + name: 抽样取证物品清单 + required: false + classifier: + title_patterns: + - 抽样取证物品清单 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 品种规格 + type: string + desc: 表格内容→品种规格、样品基数 + - name: 表格有内容 + type: enum + allowed: + - 有 + - 无 + desc: 表格是否有内容 输出 有/无 + - name: 当事人签名 + type: enum + allowed: + - 有 + - 无 + desc: 当事人签名栏 输出 有/无 +- id: 案件处理审批表 + name: 案件处理审批表 + required: true + classifier: + title_patterns: + - 案件处理审批表 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 立案编号 + type: verbatim + desc: 立案编号 + - name: 立案日期 + type: date + desc: 立案日期 + - name: 案由 + type: string + desc: 案由 + - name: 案件来源 + type: string + desc: 案件来源 + - group: 当事人-单位 + fields: + - name: 单位名称 + type: string + desc: 当事人→单位→名称 + - name: 单位法代 + type: verbatim + desc: 当事人→单位→法定代表人(负责人) + - name: 单位电话 + type: verbatim + desc: 当事人→单位→联系电话 + - name: 单位地址 + type: string + desc: 当事人→单位→地址 + - group: 当事人-个人 + fields: + - name: 个人姓名 + type: verbatim + desc: 当事人→个人(个体工商户)→姓名 + - name: 个人性别 + type: verbatim + desc: 当事人→个人→性别 + - name: 个人年龄 + type: verbatim + desc: 当事人→个人→年龄 + - name: 个人民族 + type: verbatim + desc: 当事人→个人→民族 + - name: 个人证件 + type: verbatim + desc: 当事人→个人→证件类型及号码 + - name: 个人电话 + type: verbatim + desc: 当事人→个人→联系电话 + - name: 个人住址 + type: string + desc: 当事人→个人→住址 + - group: 审批意见 + fields: + - name: 承办人意见 + type: string + desc: 承办人意见→内容 + - name: 承办人日期 + type: date + desc: 承办人意见→日期 + - name: 承办人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 承办人意见→签名1 输出 有/无 + - name: 承办人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 承办人意见→签名2 输出 有/无 + - name: 承办部门意见 + type: string + desc: 承办部门意见→内容 + - name: 承办部门日期 + type: date + desc: 承办部门意见→日期 + - name: 承办部门签名 + type: enum + allowed: + - 有 + - 无 + desc: 承办部门意见→签名 输出 有/无 + - name: 法制部门意见 + type: string + desc: 法制部门意见→内容 + - name: 法制部门日期 + type: date + desc: 法制部门意见→日期 + - name: 法制部门审核人签名 + type: enum + allowed: + - 有 + - 无 + desc: 法制部门意见→审核人签名 输出 有/无 + - name: 法制部门负责人签名 + type: enum + allowed: + - 有 + - 无 + desc: 法制部门意见→负责人签名 输出 有/无 + - name: 负责人意见 + type: string + desc: 负责人意见→内容 + - name: 负责人日期 + type: date + desc: 负责人意见→日期 + - name: 负责人签名 + type: enum + allowed: + - 有 + - 无 + desc: 负责人意见→签名 输出 有/无 +- id: 案件调查终结报告 + name: 案件调查终结报告 + required: true + classifier: + title_patterns: + - 案件调查终结报告 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 立案日期 + type: date + desc: 立案日期 + - name: 案由 + type: string + desc: 案由 + - name: 案件来源 + type: string + desc: 案件来源 + - group: 当事人-单位 + fields: + - name: 单位名称 + type: string + desc: 当事人→单位→名称 + - name: 单位法代 + type: verbatim + desc: 当事人→单位→法定代表人(负责人) + - name: 单位电话 + type: verbatim + desc: 当事人→单位→联系电话 + - name: 单位地址 + type: string + desc: 当事人→单位→地址 + - group: 当事人-个人 + fields: + - name: 个人姓名 + type: verbatim + desc: 当事人→个人(个体工商户)→姓名 + - name: 个人性别 + type: enum + allowed: + - 男 + - 女 + desc: 当事人→个人→性别 + - name: 个人年龄 + type: verbatim + desc: 当事人→个人→年龄 + - name: 个人民族 + type: verbatim + desc: 当事人→个人→民族 + - name: 个人证件 + type: verbatim + desc: 当事人→个人→证件类型及号码 + - name: 个人电话 + type: verbatim + desc: 当事人→个人→联系电话 + - name: 个人住址 + type: string + desc: 当事人→个人→住址 + - group: 处理意见 + fields: + - name: 处理意见日期 + type: date + desc: 处理意见→日期 + - name: 处理意见承办人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 处理意见→承办人签名1 输出 有/无 + - name: 处理意见承办人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 处理意见→承办人签名2 输出 有/无 +- id: 涉案物品核价表 + name: 涉案物品核价表 + required: false + classifier: + title_patterns: + - 涉案物品核价表 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 核价组印章 + type: enum + allowed: + - 有 + - 无 + desc: 涉案卷烟价格管理小组印章 输出 有/无 + - name: 核价明细 + type: string + desc: 表格内容→品种规格、数量(单位:条)、单价(元)、合计(元)、备注 + - name: 表格全文 + type: string + desc: 核价表完整内容 +- id: 涉案物品返还清单 + name: 涉案物品返还清单 + required: false + classifier: + title_patterns: + - 涉案物品返还清单 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 日期 + type: date + desc: 日期 + - name: 补偿信息 + type: verbatim + desc: 补偿信息 + - name: 返还明细 + type: string + desc: 表格内容→品种规格、数量(单位:条)、单价(元)、合计(元)、备注 + - name: 返还确认 + type: verbatim + desc: 返还确认 + - name: 接收人签名 + type: enum + allowed: + - 有 + - 无 + desc: 接收人→签名 输出 有/无 + - name: 接收单位印章 + type: enum + allowed: + - 有 + - 无 + desc: 接收单位→印章 输出 有/无 +- id: 现场笔录 + name: 现场笔录 + required: true + classifier: + title_patterns: + - 现场笔录 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 检查时间 + type: verbatim + desc: 检查时间 + - name: 检查地点 + type: verbatim + desc: 检查地点 + - group: 被检查人 + fields: + - name: 单位名称 + type: string + desc: 被检查人→单位→名称 + - name: 单位法代 + type: verbatim + desc: 法定代表人(负责人) + - name: 单位许可证号 + type: verbatim + desc: 烟草专卖许可证号码 + - name: 个人姓名 + type: verbatim + desc: 被检查人→个人→姓名 + - name: 个人性别 + type: enum + allowed: + - 男 + - 女 + desc: 被检查人→个人→性别 + - name: 个人证件 + type: verbatim + desc: 被检查人→个人→证件类型及号码 + - name: 地址 + type: string + desc: 被检查人→地址 + - name: 电话 + type: verbatim + desc: 被检查人→联系电话 + - name: 现场负责人 + type: verbatim + desc: 现场负责人→姓名、性别、证件类型及号码、与被检查人关系 + - group: 签名意见 + fields: + - name: 意见 + type: verbatim + desc: 被检查人或现场负责人→意见 + - name: 意见日期 + type: date + desc: 被检查人或现场负责人(签名)→日期 + - name: 意见签名 + type: enum + allowed: + - 有 + - 无 + desc: 被检查人或现场负责人(签名)输出 有/无 +- id: 立案报告表 + name: 立案报告表 + required: true + classifier: + title_patterns: + - 立案报告表 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 立案编号 + type: verbatim + desc: 立案编号 如"郁烟立〔2024〕第35号" + - name: 案由 + type: string + desc: 案由 + - name: 案件来源 + type: string + desc: 案件来源 如"投诉举报" + - name: 案发时间 + type: verbatim + desc: 案发时间 + - name: 案发地点 + type: verbatim + desc: 案发地点 + - group: 当事人-单位 + fields: + - name: 单位名称 + type: string + desc: 当事人→单位→名称 + - name: 单位法代 + type: verbatim + desc: 当事人→单位→法定代表人(负责人) + - name: 单位电话 + type: verbatim + desc: 当事人→单位→联系电话 + - name: 单位地址 + type: string + desc: 当事人→单位→地址 + - group: 当事人-个人 + fields: + - name: 个人姓名 + type: verbatim + desc: 当事人→个人(个体工商户)→姓名 + - name: 个人性别 + type: verbatim + desc: 当事人→个人→性别 + - name: 个人年龄 + type: verbatim + desc: 当事人→个人→年龄 + - name: 个人民族 + type: verbatim + desc: 当事人→个人→民族 + - name: 个人证件 + type: verbatim + desc: 当事人→个人→证件类型及号码 + - name: 个人身份证号 + type: chinese-id + desc: 当事人→个人→居民身份证号码 + - name: 个人电话 + type: verbatim + desc: 当事人→个人→联系电话 + - name: 个人住址 + type: string + desc: 当事人→个人→住址 + - group: 案情 + fields: + - name: 案情摘要 + type: string + desc: 案情摘要正文 + - name: 案情品种 + type: string + desc: 案情摘要中的品种规格、单位、数量 + - group: 审批意见 + fields: + - name: 承办人意见 + type: string + desc: 承办人意见→意见 + - name: 承办人日期 + type: date + desc: 承办人意见→日期 + - name: 承办人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 承办人意见→签名1 输出 有/无 + - name: 承办人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 承办人意见→签名2 输出 有/无 + - name: 承办部门意见 + type: string + desc: 承办部门意见→意见 + - name: 承办部门日期 + type: date + desc: 承办部门意见→日期 + - name: 承办部门签名 + type: enum + allowed: + - 有 + - 无 + desc: 承办部门意见→签名 输出 有/无 + - name: 负责人意见 + type: string + desc: 负责人意见→意见内容 + - name: 负责人日期 + type: date + desc: 负责人意见→日期 + - name: 负责人签名 + type: enum + allowed: + - 有 + - 无 + desc: 负责人意见→签名 输出 有/无 +- id: 结案报告表 + name: 结案报告表 + required: true + classifier: + title_patterns: + - 结案报告表 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 当事人 + type: verbatim + desc: 当事人 + - name: 执行情况 + type: string + desc: 执行情况 + - group: 审批意见 + fields: + - name: 承办人结案理由 + type: string + desc: 承办人结案理由→内容 + - name: 承办人结案日期 + type: date + desc: 承办人结案理由→日期 + - name: 承办人结案签名1 + type: enum + allowed: + - 有 + - 无 + desc: 承办人结案理由→签名1 输出 有/无 + - name: 承办人结案签名2 + type: enum + allowed: + - 有 + - 无 + desc: 承办人结案理由→签名2 输出 有/无 + - name: 承办部门意见 + type: string + desc: 承办部门意见→内容 + - name: 承办部门日期 + type: date + desc: 承办部门意见→日期 + - name: 承办部门签名 + type: enum + allowed: + - 有 + - 无 + desc: 承办部门意见→签名 输出 有/无 + - name: 负责人意见 + type: string + desc: 负责人意见→内容 + - name: 负责人日期 + type: date + desc: 负责人意见→日期 + - name: 负责人签名 + type: enum + allowed: + - 有 + - 无 + desc: 负责人意见→签名 输出 有/无 +- id: 缴款凭证 + name: 缴款凭证 + required: false + classifier: + title_patterns: + - 缴款凭证 + - 广东省非税收入一般缴款书[((]电子[))] + - 广东省非税收入一般缴款书(电子) + keywords: + - 非税收入 + - 缴款书 + - 收费项目 + - 收入项目 + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 收入项目 + type: string + desc: 收入项目名称(电子非税缴款书上可能写作"收费项目") + - name: 金额 + type: money + desc: 金额 + - name: 备注 + type: verbatim + desc: 备注 +- id: 行政处罚事先告知书 + name: 行政处罚事先告知书 + required: true + classifier: + title_patterns: + - 行政处罚事先告知书 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 当事人 + type: verbatim + desc: 当事人 + - name: 正文前称呼 + type: string + desc: 正文前称呼 + - name: 权利告知 + type: string + desc: 正文→权利告知 +- id: 证据先行登记保存批准书 + name: 证据先行登记保存批准书 + required: false + classifier: + title_patterns: + - 证据先行登记保存批准书 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 标题下方文本 + type: string + desc: 标题下方文本 + - name: 表格下方文字 + type: string + desc: 表格下方文字 含"对先行登记保存的证据,应当在...日内处理" + - name: 表格品规 + type: string + desc: 表格内容→品种规格、单位、数量 + - name: 表格全文 + type: string + desc: 表格完整内容 + - name: 盖章 + type: enum + allowed: + - 有 + - 无 + desc: 行政机关盖章 输出 有/无 + - group: 承办人 + fields: + - name: 承办人日期 + type: date + desc: 承办人→日期 + - name: 承办人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 承办人→签名1 输出 有/无 + - name: 承办人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 承办人→签名2 输出 有/无 + - group: 负责人 + fields: + - name: 负责人意见 + type: verbatim + desc: 负责人意见并签名→意见内容 + - name: 负责人意见有无 + type: enum + allowed: + - 有 + - 无 + desc: 负责人意见并签名→是否有意见 输出 有/无 + - name: 负责人日期 + type: date + desc: 负责人意见并签名→日期 + - name: 负责人签名姓名 + type: verbatim + desc: 负责人意见并签名→签名姓名 + - name: 负责人签名有无 + type: enum + allowed: + - 有 + - 无 + desc: 负责人意见并签名→是否有签名 输出 有/无 +- id: 证据先行登记保存通知书 + name: 证据先行登记保存通知书 + required: false + classifier: + title_patterns: + - 证据先行登记保存通知书 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 表格下方文字 + type: string + desc: 表格下方文字 + - name: 表格品规 + type: string + desc: 表格内容→品种规格、单位、数量 + - name: 表格全文 + type: string + desc: 表格完整内容 + - name: 盖章 + type: enum + allowed: + - 有 + - 无 + desc: 行政机关盖章 输出 有/无 + - name: 拒绝签名说明 + type: string + desc: 正文→拒绝签名说明 + - name: 当事人签名 + type: enum + allowed: + - 有 + - 无 + desc: 当事人签名 输出 有/无 + - group: 承办人 + fields: + - name: 承办人日期 + type: date + desc: 承办人→日期 + - name: 承办人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 承办人→签名1 输出 有/无 + - name: 承办人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 承办人→签名2 输出 有/无 +- id: 证据复制(提取)单 + name: 证据复制(提取)单 + required: true + classifier: + title_patterns: + - 证据复制[((]提取[))]单 + - 证据复制(提取)单 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 复制时间 + type: verbatim + desc: |- + 证据复制(提取)单每页末尾的「复制(提取)时间」字段。 + 一份卷宗通常有多份证据(每页一份,说明事项各异)。 + 当**多份存在**时,取**第一份**的时间(整体活动起点, + 通常也是询问笔录期间制作的那份)。 + 示例:"2024 年 4 月 19 日 19 时 30 分"。 + - name: 复制地点 + type: verbatim + desc: |- + 证据复制(提取)单每页末尾的「复制(提取)地点」字段。 + 多份存在时取**第一份**的地点(与 复制时间 同一页)。 + 示例:"郁南县南江口镇西江路 124 号"。 + - name: 现场时间 + type: verbatim + desc: |- + 证据复制(提取)单中**现场检查相片**所属那份证据的 + 「复制(提取)时间」。特征:说明事项含"现场/外观/ + 查获时拍摄/查获违法走私卷烟时"等,与执法人员到场 + 同一时段。用于和 现场笔录.检查时间 对齐。 + 如没有纯"现场检查"相片,取第一份时间。 + - name: 现场地址 + type: string + desc: |- + 证据复制(提取)单中**现场检查相片**所属那份证据的 + 「复制(提取)地点」,与 现场时间 同一份。 + 用于和 现场笔录.检查地点 对齐。 + - name: 邮件回执 + type: verbatim + desc: 邮件回执 + - group: 居民身份证 + fields: + - name: 居民身份证 + type: multi_entity + desc: |- + 证据复制(提取)单中**每一张**居民身份证图片对应的一份记录。 + 一份证据复制单通常包含多张身份证(当事人、举报人、未成年人、相关人等), + 请把每张身份证都抽取为数组中的一项,**不要**只抽"当事人那份"。 + 由派生字段「证据复制(提取)单当事人」按姓名+身份证号挑出归属当事人的那一份。 + 如果只有一张身份证,返回只包含一项的数组即可(引擎会自动把那一项判为当事人)。 + fields: + - name: 身份证姓名 + type: verbatim + desc: 该份身份证上印的姓名 + - name: 身份证性别 + type: verbatim + desc: 该份身份证上印的性别(男/女) + - name: 身份证民族 + type: verbatim + desc: 该份身份证上印的民族 + - name: 身份证住址 + type: string + desc: 该份身份证上印的住址 + - name: 身份证号 + type: chinese-id + desc: 该份身份证上印的公民身份号码(18 位) + - name: 身份证背面 + type: enum + allowed: + - 有 + - 无 + desc: 该份身份证是否包含背面(签发机关/有效期那面)有/无 + - group: 许可证 + fields: + - name: 许可证企业名称 + type: string + desc: 烟草专卖零售许可证→企业名称 + - name: 许可证经营场所 + type: string + desc: 烟草专卖零售许可证→经营场所 + - name: 许可证号 + type: verbatim + desc: 烟草专卖零售许可证→许可证号 + - name: 许可证负责人 + type: verbatim + desc: 烟草专卖零售许可证→负责人姓名 + - group: 营业执照 + fields: + - name: 执照名称 + type: string + desc: 营业执照→名称 + - name: 执照住所 + type: string + desc: 营业执照→住所 + - name: 执照法代 + type: verbatim + desc: 营业执照→法定代表人 + - name: 执照统一社会信用代码 + type: uscc + desc: 营业执照→统一社会信用代码 +- id: 询问笔录 + name: 询问笔录 + required: true + classifier: + title_patterns: + - 询问笔录 + keywords: [] + min_score: 0.5 + extract: + - group: 基本信息 + fields: + - name: 询问时间 + type: verbatim + desc: 询问时间 + - name: 询问地点 + type: verbatim + desc: 询问地点 + - group: 被询问人 + fields: + - name: 被询问人 + type: multi_entity + desc: |- + 询问笔录中**每一份**笔录记录对应的被询问人基本信息。 + 一份卷宗可能包含多次询问笔录(针对不同人员),请把**每一份**笔录 + 中的被询问人都抽取为数组中的一项,**不要**只抽"当事人那份"。 + 由派生字段「询问笔录当事人」按姓名+证件号挑出归属当事人的那一份。 + 只有一份被询问人记录时,引擎自动把那一份判为当事人。 + fields: + - name: 被询问人姓名 + type: verbatim + desc: 被询问人→姓名 + - name: 被询问人性别 + type: enum + allowed: + - 男 + - 女 + desc: 被询问人→性别 + - name: 被询问人民族 + type: verbatim + desc: 被询问人→民族 + - name: 被询问人证件 + type: verbatim + desc: 被询问人→证件类型及号码(通常是"居民身份证:xxx") + - name: 被询问人电话 + type: verbatim + desc: 被询问人→联系电话 + - name: 被询问人住址 + type: string + desc: 被询问人→住址 + - name: 被询问人经营地址 + type: string + desc: 被询问人→经营地址 + - group: 笔录正文 + fields: + - name: 执法人员信息 + type: string + desc: 正文→执法人员信息 + - name: 权利告知 + type: string + desc: 正文→权利告知内容 + - name: 被询问人核实 + type: string + desc: 正文→被询问人核实 + - name: 拒绝签名说明 + type: string + desc: 正文→拒绝签名说明 + - group: 签名 + fields: + - name: 被询问人签名 + type: enum + allowed: + - 有 + - 无 + desc: 被询问人(签名)输出 有/无 + - name: 询问人签名1 + type: enum + allowed: + - 有 + - 无 + desc: 询问人(签名)1 输出 有/无 + - name: 询问人签名2 + type: enum + allowed: + - 有 + - 无 + desc: 询问人(签名)2 输出 有/无 +- id: 送达回证 + name: 送达回证 + required: true + classifier: + title_patterns: + - 送达回证 + keywords: [] + min_score: 0.5 + # 注意:本子文档内可能拼接多份送达回证表格(立案通知/先行登记保存通知/事先告知书/ + # 处罚决定书等各一份)。以下字段只抽取"送达文书名称"含"行政处罚决定书"的那份; + # 其他送达回证忽略(由专门的规则处理)。 + extract: + - group: 基本信息 + fields: + - name: 受送达人 + type: verbatim + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份表格里的受送达人 + - name: 回证编号 + type: verbatim + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份表格上方的回证编号 + - name: 送达方式 + type: verbatim + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份的送达方式 + - name: 送达地点 + type: verbatim + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份的送达地点 + - name: 送达文书名称 + type: string + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"的那一项(作为后续其他字段的定位基准) + - name: 送达文书文号 + type: verbatim + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份的送达文书文号 + - group: 签收 + fields: + - name: 签收日期 + type: date + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份的签收日期 + - name: 代收理由 + type: string + desc: 本子文档内若含多份送达回证,只抽"送达文书名称"含"行政处罚决定书"那份的代收人代收理由 + - name: 印章 + type: enum + allowed: + - 有 + - 无 + desc: 印章 输出 有/无 + vlm_extract_mode: always + - name: 收件人签名 + type: enum + allowed: + - 有 + - 无 + desc: 收件人签名或盖章→签名 输出 有/无 + vlm_extract_mode: always + - name: 收件人盖章 + type: enum + allowed: + - 有 + - 无 + desc: 收件人签名或盖章→盖章 输出 有/无 + vlm_extract_mode: always + - group: 送达人 + fields: + - name: 送达人签名 + type: enum + allowed: + - 有 + - 无 + desc: 送达人签名 输出 有/无 + vlm_extract_mode: always +rules: +- group: JZG-JD + rules: + - rule_id: JZ-JD-001 + name: 当事人基本情况或立案情况记载准确性 + desc: 若当事人信息与证据复制(提取)单中信息不一致,则扣分。 + risk: medium + score: 5 + scope: + - 案件处理审批表 + - 案件调查终结报告 + - 立案报告表 + - 证据复制(提取)单 + stages: + - id: '1' + check: match + pairs: + - source: 案件处理审批表.案由 + target: 案件调查终结报告.案由 + - source: 案件处理审批表.案件来源 + target: 案件调查终结报告.案件来源 + # 案件来源是开放词汇(投诉举报/群众举报/电话举报/来电举报/上级交办… + # 无穷枚举),不用 canonicalize 字典维护。字面不等时走 rescue L1 + # match 做语义等价判定。 + - source: 案件处理审批表.立案编号 + target: 立案报告表.立案编号 + - source: 案件处理审批表.立案日期 + target: 案件调查终结报告.立案日期 + - source: 案件处理审批表.单位名称 + target: 案件调查终结报告.单位名称 + when: "当事人类型 != '个人'" + - source: 案件调查终结报告.单位名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 案件处理审批表.单位法代 + target: 案件调查终结报告.单位法代 + when: "当事人类型 != '个人'" + - source: 案件调查终结报告.单位法代 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 案件处理审批表.单位地址 + target: 案件调查终结报告.单位地址 + when: "当事人类型 != '个人'" + - source: 案件调查终结报告.单位地址 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '2' + check: match + pairs: + - source: 案件处理审批表.案由 + target: 案件调查终结报告.案由 + - source: 案件处理审批表.案件来源 + target: 案件调查终结报告.案件来源 + # 案件来源是开放词汇(投诉举报/群众举报/电话举报/来电举报/上级交办… + # 无穷枚举),不用 canonicalize 字典维护。字面不等时走 rescue L1 + # match 做语义等价判定。 + - source: 案件处理审批表.立案日期 + target: 案件调查终结报告.立案日期 + - source: 案件处理审批表.立案编号 + target: 立案报告表.立案编号 + - source: 案件处理审批表.个人姓名 + target: 案件调查终结报告.个人姓名 + when: "当事人类型 != '单位'" + - source: 案件处理审批表.个人性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人民族 + target: 证据复制(提取)单当事人.身份证民族 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人证件 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + method: substring + - source: 案件处理审批表.个人住址 + target: 案件调查终结报告.个人住址 + when: "当事人类型 != '单位'" + - id: '3' + check: ai + prompt: "请根据以下卷宗信息,判断当事人基本情况及立案情况的记载是否准确一致。\n\n 【第一步:判断案件类型】\n\n 检查\"案件处理审批表\"\ + 中的当事人单位名称字段值:\n {{案件处理审批表.单位名称}}\n\n - 如果该值为 \"/\"、\"-\"、空或其他占位符 → 这是**个人案件**,执行个人案件检查\n\ + \ - 如果该值是真实的单位名称 → 这是**单位案件**,执行单位案件检查\n\n ---\n\n 【第二步-A:单位案件检查】(当事人为单位时执行)\n\ + \n 请逐一比对以下字段,判断是否一致:\n\n 1. 案由\n - 案件处理审批表:{{案件处理审批表.案由}}\n - 案件调查终结报告:{{案件调查终结报告.案由}}\n\ + \n 2. 案件来源\n - 案件处理审批表:{{案件处理审批表.案件来源}}\n - 案件调查终结报告:{{案件调查终结报告.案件来源}}\n\n\ + \ 3. 立案编号\n - 案件处理审批表:{{案件处理审批表.立案编号}}\n - 立案报告表:{{立案报告表.立案编号}}\n\n 4. 立案日期\n\ + \ - 案件处理审批表:{{案件处理审批表.立案日期}}\n - 案件调查终结报告:{{案件调查终结报告.立案日期}}\n\n 5. 单位名称(三方核对)\n\ + \ - 案件处理审批表:{{案件处理审批表.单位名称}}\n - 案件调查终结报告:{{案件调查终结报告.单位名称}}\n - 证据复制(提取)单-营业执照:{{证据复制(提取)单.执照名称}}\n\ + \n 6. 法定代表人(三方核对)\n - 案件处理审批表:{{案件处理审批表.单位法代}}\n - 案件调查终结报告:{{案件调查终结报告.单位法代}}\n\ + \ - 证据复制(提取)单-营业执照:{{证据复制(提取)单.执照法代}}\n\n 7. 单位地址(三方核对)\n - 案件处理审批表:{{案件处理审批表.单位地址}}\n\ + \ - 案件调查终结报告:{{案件调查终结报告.单位地址}}\n - 证据复制(提取)单-营业执照:{{证据复制(提取)单.执照住所}}\n\n \ + \ ---\n\n 【第二步-B:个人案件检查】(当事人为个人或个体工商户时执行)\n\n 请逐一比对以下字段,判断是否一致:\n\n 1.\ + \ 案由\n - 案件处理审批表:{{案件处理审批表.案由}}\n - 案件调查终结报告:{{案件调查终结报告.案由}}\n\n 2. 案件来源\n\ + \ - 案件处理审批表:{{案件处理审批表.案件来源}}\n - 案件调查终结报告:{{案件调查终结报告.案件来源}}\n\n 3. 立案编号\n\ + \ - 案件处理审批表:{{案件处理审批表.立案编号}}\n - 立案报告表:{{立案报告表.立案编号}}\n\n 4. 立案日期\n - 案件处理审批表:{{案件处理审批表.立案日期}}\n\ + \ - 案件调查终结报告:{{案件调查终结报告.立案日期}}\n\n 5. 姓名\n - 案件处理审批表:{{案件处理审批表.个人姓名}}\n -\ + \ 案件调查终结报告:{{案件调查终结报告.个人姓名}}\n\n 6. 性别\n - 案件处理审批表:{{案件处理审批表.个人性别}}\n - 证据复制(提取)单-居民身份证:{{证据复制(提取)单当事人.身份证性别}}\n\ + \n 7. 民族\n - 案件调查终结报告:{{案件调查终结报告.个人民族}}\n - 证据复制(提取)单-居民身份证:{{证据复制(提取)单当事人.身份证民族}}\n\ + \n 8. 证件号码(包含匹配)\n - 案件调查终结报告:{{案件调查终结报告.个人证件}}\n - 证据复制(提取)单-居民身份证:{{证据复制(提取)单当事人.身份证号}}\n\ + \ - 注意:审批表中证件字段格式可能为\"居民身份证:44xxxxxxxx\",判断时应提取纯号码部分进行比对\n\n 9. 住址\n - 案件处理审批表:{{案件处理审批表.个人住址}}\n\ + \ - 证据复制(提取)单-居民身份证:{{证据复制(提取)单当事人.身份证住址}}\n\n ---\n\n 【判断规则】\n\n - \"/\"\ + 、\"-\"、\"—\" 等符号代表该字段不适用,不是有效值,遇到此类值的比对项直接跳过\n - 只要有任意一个有效字段不一致,判定为**不通过**\n\ + \ - 所有有效字段均一致(或均为占位符可跳过),判定为**通过**\n" + logic: 1 OR 2 OR 3 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第五十九条 + type: ai_rule + - rule_id: JZ-JD-002 + name: 处罚决定书证据列举 + desc: 若找不到"证据:"或者"证据:"之后无内容,则扣分。 + risk: medium + score: 10 + scope: + - 处罚决定书 + stages: + - id: '1' + check: required + field: 处罚决定书.证据列举 + messages: + pass: 处罚决定书已列出相关证据。 + fail: 罚决定书未列出相关证据,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十九条 + type: deterministic + - rule_id: JZ-JD-003 + name: 救济途径或期限告知明确性 + desc: 若未找到文本匹配内容,则扣分。 + risk: medium + score: 5 + scope: + - 处罚决定书 + stages: + - id: '1' + check: required + field: 处罚决定书.救济途径 + messages: + pass: 已告知救济途径和期限。 + fail: 救济途径或期限告知不明确或不正确,请核对。 + references_laws: + - 《中华人民共和国烟草专卖法》第四十一条 + type: deterministic + - rule_id: JZ-JD-004 + name: 行政处罚决定当事人基本情况记载准确性 + desc: 检查首段信息是否填写齐全,若存在未填内容,(字号:可为空),若不齐全,则扣分。 若当事人信息与证据中提取的信息不一致,则扣分。 + risk: medium + score: 10 + scope: + - 处罚决定书 + - 证据复制(提取)单 + stages: + - id: '1' + check: match + pairs: + - source: 处罚决定书.当事人 + target: 证据复制(提取)单.许可证企业名称 + when: "当事人类型 != '个人'" + - source: 处罚决定书.字号 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 处罚决定书.统一社会信用代码 + target: 证据复制(提取)单.执照统一社会信用代码 + when: "当事人类型 != '个人'" + - source: 处罚决定书.经营地址 + target: 证据复制(提取)单.许可证经营场所 + when: "当事人类型 != '个人'" + - source: 证据复制(提取)单.许可证经营场所 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '2' + check: match + pairs: + - source: 处罚决定书.当事人 + target: 证据复制(提取)单当事人.身份证姓名 + when: "当事人类型 != '单位'" + - source: 处罚决定书.性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 处罚决定书.民族 + target: 证据复制(提取)单当事人.身份证民族 + when: "当事人类型 != '单位'" + - source: 处罚决定书.身份证住址 + target: 证据复制(提取)单当事人.身份证住址 + when: "当事人类型 != '单位'" + - source: 处罚决定书.身份证号码 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + - source: 处罚决定书.经营地址 + target: 证据复制(提取)单.许可证经营场所 + when: "当事人类型 != '个人'" + - source: 证据复制(提取)单.许可证经营场所 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - source: 处罚决定书.字号 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + logic: 1 OR 2 + messages: + pass: 当事人的基本情况记载齐全且准确。 + fail: 当事人的基本情况记载不齐全或不准确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十九条 + type: deterministic +- group: JZG-SD + rules: + - rule_id: JZ-SD-001 + name: 法定时限送达 + desc: 若处罚决定书文尾的日期与处罚决定书的送达回证中的"签收日期",之间的范围不在法定时限内,则扣分。 + risk: medium + score: 10 + scope: + - 处罚决定书 + - 送达回证 + stages: + - id: '1' + check: required + fields: + - 送达回证.签收日期 + - 处罚决定书.落款日期 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第六十一条 + type: deterministic + - rule_id: JZ-SD-002 + name: 送达回证基本信息规范 + desc: 若收件人签名、签收时间、送达人签名、印章任意一项不存在,则扣分 + risk: medium + score: 10 + scope: + - 送达回证 + stages: + - id: '1' + check: required + fields: + - 送达回证.回证编号 + - 送达回证.送达文书名称 + - 送达回证.送达方式 + - 送达回证.签收日期 + messages: + pass: 办案单位印章、送达人签名、收件人签名及签收时间填写规范。 + fail: 填写不规范,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第六十一条 + type: deterministic +- group: JZG-XC + rules: + - rule_id: JZ-XC-001 + name: 现场笔录时间地点完整性 + desc: 若现场笔录中时间或地点未记载,则扣分;若记载的时间与证据提取单中的时间、地点不一致,也扣分。 + risk: medium + score: 10 + scope: + - 现场笔录 + - 证据复制(提取)单 + stages: + # 地点是文字型字段,用确定性 match 足够(fuzzy 可容忍小差异) + - id: '1' + check: match + pairs: + - source: 现场笔录.检查地点 + target: 证据复制(提取)单.现场地址 + method: fuzzy + # 时间是语义型字段 —— 现场笔录.检查时间常是时间段("16:10至17:00"), + # 证据复制(提取)单.现场时间常是时间点("16:20")。不写字符串 parser, + # 直接让 LLM 按业务语义判定(点落在段内视为一致)。 + - id: '2' + check: ai + prompt: | + 判断以下两个时间在业务上是否一致: + + - 现场笔录.检查时间:{{现场笔录.检查时间}} + - 证据复制(提取)单.现场时间:{{证据复制(提取)单.现场时间}} + + 判断原则: + - 若两者都是时间点且值相同 → 一致 + - 若一方是时间段,另一方是时间点,且**点落在段内** → 一致 + - 若两者都是时间段且有重叠 → 一致 + - 若完全无关或对不上 → 不一致 + + 只判时间业务语义,不判格式差异("2024 年 11 月 18 日"和"2024-11-18"视为同日)。 + logic: 1 AND 2 + messages: + pass: 时间地点记录准确。 + fail: 时间地点记录缺失或与实际不一致,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + - rule_id: JZ-XC-002 + name: 被检查人基本情况记载完整性-有无 + desc: 被检查人基本情况记载 + risk: medium + score: 10 + scope: + - 现场笔录 + stages: + - id: '1' + check: required + fields: + - 现场笔录.单位名称 + - 现场笔录.单位法代 + - 现场笔录.地址 + - 现场笔录.电话 + - 现场笔录.单位许可证号 + - id: '2' + check: required + fields: + - 现场笔录.个人姓名 + - 现场笔录.个人性别 + - 现场笔录.个人证件 + - 现场笔录.地址 + - 现场笔录.电话 + - id: '3' + check: required + fields: + - 现场笔录.现场负责人 + - 现场笔录.电话 + - 现场笔录.地址 + logic: (1 OR 2) AND 3 + messages: + pass: 被检查人姓名、身份证号、地址、许可证号与证据一致,请检查其余基本信息是否完整准确。 + fail: 被检查人基本情况记录有误或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + - rule_id: JZ-XC-003 + name: 被检查人基本情况记载完整性-一致 + desc: 检查现场笔录中被检查人信息与身份证/营业执照/许可证信息是否一致 + risk: medium + score: 10 + scope: + - 现场笔录 + - 立案报告表 + - 证据复制(提取)单 + stages: + - id: '1' + check: match + pairs: + - source: 现场笔录.单位名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 现场笔录.单位法代 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 现场笔录.单位许可证号 + target: 证据复制(提取)单.许可证号 + when: "当事人类型 != '个人'" + - source: 证据复制(提取)单.许可证企业名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 证据复制(提取)单.许可证负责人 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 立案报告表.单位名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 立案报告表.单位法代 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 立案报告表.单位地址 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '2' + check: match + pairs: + - source: 现场笔录.个人姓名 + target: 立案报告表.个人姓名 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人姓名 + target: 证据复制(提取)单当事人.身份证姓名 + when: "当事人类型 != '单位'" + - source: 现场笔录.个人性别 + target: 立案报告表.个人性别 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 现场笔录.个人证件 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + - source: 现场笔录.地址 + target: 立案报告表.个人住址 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人住址 + target: 证据复制(提取)单当事人.身份证住址 + when: "当事人类型 != '单位'" + logic: 1 OR 2 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + - rule_id: JZ-XC-004 + name: 被检查人签署意见合规性 + desc: 若被检查人拒绝签署意见及姓名,且执法人员未说明情况,则扣分。 + risk: medium + score: 10 + scope: + - 现场笔录 + stages: + - id: '1' + check: required + fields: + - 现场笔录.意见 + - 现场笔录.意见日期 + - 现场笔录.意见签名 + - id: '2' + check: required + field: 现场笔录.意见 + messages: + pass: 被检查人已签署意见及姓名,或执法人员已说明拒绝签署的情况。 + fail: 被检查人拒绝签署但执法人员未说明情况,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic +- group: JZG-DJ + rules: + - rule_id: JZ-DJ-001 + name: 批准保存时间记载完整性 + desc: 若负责人意见并签名栏后没有日期信息,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + stages: + - id: '1' + check: required + field: 证据先行登记保存批准书.负责人日期 + messages: + pass: 已记载批准保存时间。 + fail: 批准保存时间未记载,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None + - rule_id: JZ-DJ-002 + name: 证据先行登记保存批准书负责人意见并签名 + desc: 若行政机关负责人没有签署意见或姓名,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.负责人签名姓名 + - 证据先行登记保存批准书.负责人意见 + - 证据先行登记保存批准书.负责人日期 + messages: + pass: 行政机关负责人已签署意见和姓名。 + fail: 行政机关负责人未签署意见或姓名,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None + - rule_id: JZ-DJ-003 + name: 先行登记保存证据期限记载 + desc: 若没有文中"对先行登记保存的证据,应当在.....日内及时作出处理决定。"的描述,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.表格下方文字 + - 证据先行登记保存通知书.表格下方文字 + messages: + pass: 已注明先行登记保存证据期限和处理决定期限。 + fail: 未注明相关期限,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None and 证据先行登记保存通知书 != None + - rule_id: JZ-DJ-004 + name: 先行登记保存批准书或通知书文件校验 + desc: 若现场笔录中的情况说明中出现物品名称及规格描述,且文件中无批准书或通知书,则扣分。 + risk: medium + score: 10 + scope: + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.表格品规 + - 证据先行登记保存通知书.表格品规 + - id: '2' + check: ai + prompt: '请判断以下 {{证据先行登记保存批准书.表格全文}} 和 {{证据先行登记保存通知书.表格全文}} 表述和数量一致 + + ' + messages: + pass: 存在先行登记保存批准书或通知书。 + fail: 缺少先行登记保存批准书或通知书,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule + activate_if: 证据先行登记保存批准书 != None and 证据先行登记保存通知书 != None + - rule_id: JZ-DJ-005 + name: 批准书与通知书内容一致性 + desc: 若批准书和通知书内容不一致,则直接扣分;若一致,则与抽样清单中的物品数量进行比对,如果抽样清单中同一品种有多条记录则提示。 若当事人和见证人栏均无签名,则扣分 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: match + pairs: + - source: 证据先行登记保存通知书.表格品规 + target: 证据先行登记保存批准书.表格品规 + messages: + pass: 批准书与通知书内容一致 + fail: 批准书与通知书内容不一致,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None and 证据先行登记保存通知书 != None + - rule_id: JZ-DJ-006 + name: 证据先行登记保存批准/通知书承办人签名日期 + desc: 若没有证据先行登记保存批准/通知书承办人签字或盖章,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.承办人日期 + - 证据先行登记保存通知书.承办人日期 + - 证据先行登记保存批准书.承办人签名1 + - 证据先行登记保存批准书.承办人签名2 + - 证据先行登记保存通知书.承办人签名1 + - 证据先行登记保存通知书.承办人签名2 + messages: + pass: 有日期,案件承办人已签字或盖章。 + fail: 缺少印章、日期或承办人签字盖章,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None and 证据先行登记保存通知书 != None + - rule_id: JZ-DJ-007 + name: 证据先行登记保存批准书负责人意见并签名 + desc: 若没有填写两名承办人意见及签名,负责人意见及签名,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.负责人日期 + - 证据先行登记保存批准书.负责人签名有无 + - 证据先行登记保存批准书.负责人意见有无 + messages: + pass: 两名承办人签名,负责人意见及签名完整。 + fail: 两名承办人签名或负责人意见及签名缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None + - rule_id: JZ-DJ-008 + name: 保存理由和内容记载完整性 + desc: 若首部没有保存理由描述,表格中没有规格和数量信息,则扣分。 + risk: medium + score: 10 + scope: + - 立案报告表 + - 证据先行登记保存批准书 + stages: + - id: '1' + check: ai + prompt: '{{立案报告表.案由}} + + {{证据先行登记保存批准书.标题下方文本}} + + 案由应该要和标题下方文本同一个意思,案由会比较少字。帮我评查这个案由是否存在 在标题下方文本 中 + + ' + - id: '2' + check: ai + prompt: '{{立案报告表.案情品种}}中提及的具体规格品种、数量应出现在{{证据先行登记保存批准书.表格品规}}中,但案情摘要中不一定会将全部规格品种都写全,评查尺度可以适当放松 + + ' + - id: '3' + check: ai + prompt: '请根据以下信息判断案件类型,对个人(个体工商户)案件单独评查证据先行登记保存批准书内容是否完整。 + + + 当事人-单位-名称: {{立案报告表.单位名称}} + + 当事人-个人(个体工商户)-姓名: {{立案报告表.个人姓名}} + + 证据先行登记保存批准书-表格内容-品种规格、单位、数量: {{证据先行登记保存批准书.表格品规}} + + + 判断逻辑: + + 1. 如果单位-名称为空或为"/",且个人-姓名不为空,则这是个人(个体工商户)案件 + + 2. 对于个人案件:只要证据先行登记保存批准书-表格内容-品种规格、单位、数量有内容(非空);若为空 + + 3. 如果单位-名称有实际值(非空、非"/") + + ' + logic: (1 AND 2) OR 3 + messages: + pass: 已注明保存理由和内容。 + fail: 保存理由和内容未注明,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule + activate_if: 证据先行登记保存批准书 != None + - rule_id: JZ-DJ-009 + name: 先行登记保存物品处理通知书当事人签字 + desc: 若通知书中当事人未签字或没有其他内容说明,则扣分。 + risk: medium + score: 5 + scope: + - 证据先行登记保存通知书 + stages: + - id: '1' + check: required + field: 证据先行登记保存通知书.当事人签名 + - id: '2' + check: required + field: 证据先行登记保存通知书.拒绝签名说明 + logic: 1 OR 2 + messages: + pass: 当事人已在先行登记保存物品处理通知书上签字。 + fail: 当事人未签字或i没有情况说明,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存通知书 != None + - rule_id: JZ-DJ-010 + name: 证据先行登记保存批准书负责人意见并签名 + desc: 检查涉案物品返还清单接收人签名、日期和印章是否完整,并通过正则检查损耗/返还信息 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.负责人意见 + - 证据先行登记保存批准书.负责人签名姓名 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None + - rule_id: JZ-DJ-011 + name: 证据先行登记保存批准/通知书盖章 + desc: 检查先行登记保存批准书和通知书是否加盖行政机关印章 + risk: medium + score: 5 + scope: + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: required + fields: + - 证据先行登记保存批准书.盖章 + - 证据先行登记保存通知书.盖章 + messages: + pass: 有行政机关印章 + fail: 缺少印章,请核对 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 证据先行登记保存批准书 != None and 证据先行登记保存通知书 != None +- group: JZG-QR + rules: + - rule_id: JZ-QR-001 + name: 陈述申辩权利告知和听取 + desc: 若表述中不包含"享有陈述权和申辩权"、"...日内"、"...视为放弃",任意一项,则扣分, + risk: medium + score: 10 + scope: + - 行政处罚事先告知书 + stages: + - id: '1' + check: required + field: 行政处罚事先告知书.权利告知 + messages: + pass: 已告知当事人陈述申辩权利。 + fail: 未告知当事人陈述申辩相关权力,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第四十四条 + type: deterministic + - rule_id: JZ-QR-002 + name: 行政处罚事先告知对象准确性 + desc: 若告知书首句中的姓名与当事人意见中的签名不一致,则扣分。 + risk: medium + score: 10 + scope: + - 行政处罚事先告知书 + stages: + - id: '1' + check: match + pairs: + - source: 行政处罚事先告知书.当事人 + target: 行政处罚事先告知书.正文前称呼 + messages: + pass: 行政处罚事先告知对象正确。 + fail: 行政处罚事先告知对象错误,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第四十四条 + type: deterministic +- group: JZG-QZ + rules: + - rule_id: JZ-QZ-001 + name: 当事人身份证明提取规范性 + desc: 若没有提取当事人身份证明,则扣分。 + risk: medium + score: 10 + scope: + - 证据复制(提取)单 + stages: + - id: '1' + check: required + fields: + - 证据复制(提取)单当事人.身份证号 + - 证据复制(提取)单当事人.身份证背面 + messages: + pass: 当事人身份证明已规范提取。 + fail: 当事人身份证明提取不规范或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + - rule_id: JZ-QZ-002 + name: 查获物品情况记载准确性、合规性 + desc: 若批准书和通知书内容不一致,则直接扣分;若一致,则与抽样清单中的物品数量进行比对,如果抽样清单中同一品种有多条记录则提示。 若当事人和见证人栏均无签名,则扣分 + risk: medium + score: 10 + scope: + - 抽样取证物品清单 + - 涉案物品核价表 + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: ai + prompt: '请判断{{抽样取证物品清单.品种规格}}(若有)或{{涉案物品核价表.核价明细}},以及{{证据先行登记保存批准书.表格品规}}、{{证据先行登记保存通知书.表格品规}}表述和数量一致。 + + 如果{{抽样取证物品清单.品种规格}}、{{涉案物品核价表.核价明细}}都不存在,则只需判断{{证据先行登记保存批准书.表格品规}}和{{证据先行登记保存通知书.表格品规}}的一致性 + + ' + messages: + pass: 查获物品情况、数量及当事人或见证人姓名记录准确。 + fail: 记录不准确或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule + - rule_id: JZ-QZ-003 + name: 核价文书记录的准确性(盖章) + desc: 检查涉案物品核价表是否有涉案卷烟价格管理小组印章 + risk: medium + score: 5 + scope: + - 涉案物品核价表 + stages: + - id: '1' + check: required + field: 涉案物品核价表.核价组印章 + messages: + pass: 已正确加盖印章。 + fail: 印章加盖错误,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 涉案物品核价表 != None + - rule_id: JZ-QZ-004 + name: 抽样取证物品清单完整性 + desc: 先行登记保存证据处理通知书"处理"方式选择第2项"送交...鉴定"时,卷宗内没有抽样取证物品清单,则扣分。 + risk: medium + score: 10 + scope: + - 先行登记保存证据处理通知书 + - 抽样取证物品清单 + stages: + - id: '1' + check: required + field: 先行登记保存证据处理通知书.处理方式 + - id: '2' + check: required + fields: + - 抽样取证物品清单.表格有内容 + - 抽样取证物品清单.当事人签名 + logic: (1 AND 2) OR (NOT 1) + messages: + pass: 抽样提取物证时有完整的物品清单。 + fail: 抽样提取物证时缺少物品清单,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 先行登记保存证据处理通知书 != None + - rule_id: JZ-QZ-005 + name: 核价文书记录准确性 + desc: 若核价文书或记录中没有准确记载(计算核价结果错误)涉案物品情况,核价错误,则扣分。 + risk: medium + score: 5 + scope: + - 涉案物品核价表 + stages: + - id: '1' + check: ai + prompt: '{{涉案物品核价表.表格全文}} + + 请判断以表格中各品种规格的数量、单价计算的合计金额是否正确,各品种规格合计金额计算总计金额是否正确,请在计算的时候保留小数点后两位 + + ' + messages: + pass: 涉案物件核价表存在 + fail: 涉案物件核价表不存在或者信息内容有误 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule + - rule_id: JZ-QZ-006 + name: 价格证明合规性 + desc: 若批准书与通知书内容不一致,核价表中数量与批准书或通知书中不一致,则扣分。 + risk: medium + score: 10 + scope: + - 涉案物品核价表 + - 证据先行登记保存批准书 + - 证据先行登记保存通知书 + stages: + - id: '1' + check: ai + prompt: '请判断以下三个表格物品和数量是否对应 + + {{涉案物品核价表.核价明细}} + + {{证据先行登记保存批准书.表格品规}} + + {{证据先行登记保存通知书.表格品规}} + + ' + messages: + pass: 价格证明符合要求,且有涉案物品核价依据或价格来源。 + fail: 价格证明不符合要求或缺少依据,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule +- group: JZG-XW + rules: + - rule_id: JZ-XW-001 + name: 被询问人签署"记录属实"合规性 + desc: 若每页页尾被询问人处没有签名,则扣分;如果最后一页没有手写内容则提示。 + risk: medium + score: 10 + scope: + - 询问笔录 + stages: + - id: '1' + check: required + field: 询问笔录.被询问人核实 + messages: + pass: 被询问人已签署"记录属实"且逐页签名。 + fail: 被询问人未签署或未逐页签名,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十五条 + type: deterministic + - rule_id: JZ-XW-002 + name: 询问笔录合规性 + desc: 通过AI判断询问笔录格式是否符合规范要求 + risk: medium + score: 10 + scope: + - 询问笔录 + stages: + - id: '1' + check: ai + prompt: '请判断以下询问笔录中是否只有一名被询问人。被询问人信息:{{询问笔录当事人.被询问人姓名}} + + ' + messages: + pass: 笔录仅询问一名被询问人。 + fail: 一份笔录询问多名被询问人,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十五条 + type: ai_rule + - rule_id: JZ-XW-003 + name: 执法人员身份表明和权利告知 + desc: 若未在询问开始时表明执法人员身份,并告知当事人享有陈述申辩权和申请回避权,则扣分。 + risk: medium + score: 5 + scope: + - 询问笔录 + stages: + - id: '1' + check: required + fields: + - 询问笔录.执法人员信息 + - 询问笔录.权利告知 + messages: + pass: 执法人员已表明身份并告知相关权利。 + fail: 未表明身份或未告知权利,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十五条 + type: deterministic + - rule_id: JZ-XW-004 + name: 执法人员签名合规性 + desc: 若执法人员没有签名或只有一人签名,则扣分。 + risk: medium + score: 10 + scope: + - 询问笔录 + stages: + - id: '1' + check: required + fields: + - 询问笔录.询问人签名1 + - 询问笔录.询问人签名2 + messages: + pass: 执法人员已签名,且有两人以上签名。 + fail: 执法人员签名缺失或不足两人,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第四十二条 + type: deterministic + - rule_id: JZ-XW-005 + name: 被询问人基本情况记载全面性 + desc: 被询问人基本情况填写不全,或询问时间、地点未准确记载,则扣分。 + risk: medium + score: 5 + scope: + - 证据复制(提取)单 + - 询问笔录 + stages: + - id: '1' + check: match + pairs: + - source: 询问笔录.询问地点 + target: 证据复制(提取)单.复制地点 + - source: 询问笔录当事人.被询问人姓名 + target: 证据复制(提取)单当事人.身份证姓名 + when: "当事人类型 != '单位'" + - source: 询问笔录当事人.被询问人性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 询问笔录当事人.被询问人民族 + target: 证据复制(提取)单当事人.身份证民族 + when: "当事人类型 != '单位'" + - source: 询问笔录当事人.被询问人证件 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + - source: 询问笔录当事人.被询问人住址 + target: 证据复制(提取)单当事人.身份证住址 + when: "当事人类型 != '单位'" + - source: 询问笔录.询问时间 + target: 证据复制(提取)单.复制时间 + method: fuzzy + - source: 询问笔录当事人.被询问人经营地址 + target: 证据复制(提取)单.许可证经营场所 + when: "当事人类型 != '个人'" + messages: + pass: 被询问人基本情况、询问时间地点记录完整准确。 + fail: 记录不完整或不准确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十五条 + type: deterministic + - rule_id: JZ-XW-006 + name: 被询问人拒绝签署处理合规性 + desc: 检查被询问人拒绝签名时是否有情况说明记录 + risk: medium + score: 10 + scope: + - 询问笔录 + stages: + - id: '1' + check: required + field: 询问笔录.被询问人签名 + - id: '2' + check: required + field: 询问笔录.拒绝签名说明 + logic: 1 OR 2 + messages: + pass: 被询问人已签署或已记载拒绝情况。 + fail: 被询问人未签署且未记录情况说明,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十五条 + type: deterministic +- group: JZG-LA + rules: + - rule_id: JZ-LA-001 + name: 当事人基本情况记载完整、准确 + desc: 若当事人姓名、有效证件号码和地址未记载或与身份证中信息不一致,则扣分。 + risk: medium + score: 10 + scope: + - 立案报告表 + - 证据复制(提取)单 + stages: + - id: '1' + check: required + fields: + - 立案报告表.单位名称 + - 立案报告表.单位法代 + - 立案报告表.单位电话 + - 立案报告表.单位地址 + - id: '2' + check: required + fields: + - 立案报告表.个人姓名 + - 立案报告表.个人性别 + - 立案报告表.个人年龄 + - 立案报告表.个人民族 + - 立案报告表.个人证件 + - 立案报告表.个人电话 + - 立案报告表.个人住址 + - id: '3' + check: match + pairs: + - source: 立案报告表.个人姓名 + target: 证据复制(提取)单当事人.身份证姓名 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人民族 + target: 证据复制(提取)单当事人.身份证民族 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人住址 + target: 证据复制(提取)单当事人.身份证住址 + when: "当事人类型 != '单位'" + - source: 立案报告表.个人证件 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + - id: '4' + check: match + pairs: + - source: 立案报告表.单位名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 立案报告表.单位法代 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 立案报告表.单位地址 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '5' + check: match + pairs: + - source: 立案报告表.个人姓名 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 立案报告表.个人住址 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '6' + check: ai + prompt: '请根据以下信息判断案件类型(个人案件或单位案件),并评查当事人基本情况是否记载完整。 + + + 当事人-单位-名称: {{立案报告表.单位名称}} + + 当事人-单位-法定代表人(负责人): {{立案报告表.单位法代}} + + 当事人-个人(个体工商户)-姓名: {{立案报告表.个人姓名}} + + 当事人-个人(个体工商户)-性别: {{立案报告表.个人性别}} + + 当事人-个人(个体工商户)-年龄: {{立案报告表.个人年龄}} + + 当事人-个人(个体工商户)-民族: {{立案报告表.个人民族}} + + 当事人-个人(个体工商户)-证件类型及号码: {{立案报告表.个人证件}} + + 当事人-个人(个体工商户)-联系电话: {{立案报告表.个人电话}} + + 当事人-个人(个体工商户)-住址: {{立案报告表.个人住址}} + + + 判断逻辑: + + 1. 如果单位-名称为空或为"/",且个人-姓名不为空,则这是个人(个体工商户)案件 + + 2. 对于个人案件:检查个人字段(姓名、性别、年龄、民族、证件类型及号码、联系电话、住址)是否都不为空—— + + 3. 如果单位-名称有实际值(非空、非"/") + + ' + logic: (1 AND 4) OR 6 + messages: + pass: 当事人基本情况记录完整,与身份证信息一致。 + fail: 当事人基本情况记录有误或缺失,请核对。 + references_laws: + - 《中华人民共和国烟草专卖法》第三十八条 + type: ai_rule + - rule_id: JZ-LA-002 + name: 案由、发案时间和发案地点记载准确性-有无 + desc: 若案由、发案时间和发案地点未记载或错误记载,则扣分。 + risk: medium + score: 10 + scope: + - 立案报告表 + stages: + - id: '1' + check: required + field: 立案报告表.案由 + messages: + pass: 案由、发案时间和发案地点记录准确。 + fail: 案由、发案时间和发案地点记录有误或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十四条 + type: deterministic + - rule_id: JZ-LA-003 + name: 案件来源有无一致性校验 + desc: 若三处文档中的案件来源信息不一致或者存在未填写的情况,则扣分。 + risk: medium + score: 5 + scope: + - 案件处理审批表 + - 案件调查终结报告 + - 立案报告表 + stages: + - id: '1' + check: required + fields: + - 立案报告表.案件来源 + - 案件处理审批表.案件来源 + - 案件调查终结报告.案件来源 + - id: '2' + check: match + pairs: + - source: 立案报告表.案件来源 + target: 案件处理审批表.案件来源 + - source: 案件处理审批表.案件来源 + target: 案件调查终结报告.案件来源 + # 案件来源是开放词汇(投诉举报/群众举报/电话举报/来电举报/上级交办… + # 无穷枚举),不用 canonicalize 字典维护。字面不等时走 rescue L1 + # match 做语义等价判定。 + messages: + pass: 案件来源完整 + fail: 没有记载案件来源或案件来源与其他文书不一致,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十四条 + type: deterministic + - rule_id: JZ-LA-004 + name: 案由、发案时间和发案地点记载准确性-一致 + desc: 检查立案报告表案发时间/地点与现场笔录检查时间/地点是否一致 + risk: medium + score: 10 + scope: + - 现场笔录 + - 立案报告表 + stages: + - id: '1' + check: required + fields: + - 立案报告表.案发时间 + - 立案报告表.案发地点 + - 现场笔录.检查时间 + - 现场笔录.检查地点 + - id: '2' + check: match + pairs: + - source: 立案报告表.案发时间 + target: 现场笔录.检查时间 + method: substring + - id: '3' + check: match + pairs: + - source: 现场笔录.检查地点 + target: 立案报告表.案发地点 + messages: + pass: 案由、发案时间和发案地点记录准确。 + fail: 案由、发案时间和发案地点记录有误或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + - rule_id: JZ-LA-005 + name: 承办人和承办部门意见 + desc: 承办人栏无描述、无签名、承办部门处无描述、无签名,出现任一一项则扣分。 + risk: medium + score: 5 + scope: + - 立案报告表 + stages: + - id: '1' + check: required + fields: + - 立案报告表.承办部门意见 + - 立案报告表.承办部门日期 + - 立案报告表.承办人意见 + - 立案报告表.承办人日期 + - 立案报告表.承办部门签名 + - 立案报告表.承办人签名2 + - 立案报告表.承办人签名1 + messages: + pass: 承办人和承办部门意见及签名完整。 + fail: 承办人和承办部门意见及签名存在缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十四条 + type: deterministic + - rule_id: JZ-LA-006 + name: 行政机关负责人明确意见、签字和日期 + desc: 若"负责人意见"栏中存在"不同意"或"不同意和意见描述",留空则扣分。;负责人意见栏无描述、无签名、无日期,出现任一一项则扣分。 + risk: medium + score: 10 + scope: + - 立案报告表 + stages: + - id: '1' + check: required + fields: + - 立案报告表.负责人意见 + - 立案报告表.负责人签名 + messages: + pass: 行政机关负责人意见、签字和日期完整。 + fail: 行政机关负责人意见、签字和日期缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + - rule_id: JZ-LA-007 + name: 立案文书完整性检查(签名) + desc: 检查立案报告表负责人意见处是否有签名 + risk: medium + score: 10 + scope: + - 立案报告表 + stages: + - id: '1' + check: required + field: 立案报告表.负责人签名 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + - rule_id: JZ-LA-008 + name: 案件情况清晰 + desc: 通过AI检查立案报告表案由和案情摘要表述是否清晰;若案件情况描述中,需出现案件时间、货物名称、(案由描述+条款引用)中所有信息,未出现任一一项则扣分。 + risk: low + score: 1 + scope: + - 立案报告表 + stages: + - id: '1' + check: ai + prompt: | + 检查 案情摘要 是否覆盖以下 4 项要素(任一缺失才扣分): + 1. 案件时间(检查/发案时间) + 2. 涉案货物名称或品种 + 3. 案由描述(违法行为的事实陈述) + 4. 相关条款或法律依据的引用 + + 案由:{{立案报告表.案由}} + 案情摘要:{{立案报告表.案情摘要}} + + 判定规则: + - 4 项要素齐全 → pass + - 有缺项 → fail + - **不要**对文字风格、段落重复、句式冗余等格式问题扣分,只看内容是否齐全。 + messages: + pass: 案件情况描述清晰。 + fail: 案件情况记录不清晰或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十四条 + type: ai_rule +- group: JZG-ZJ + rules: + - rule_id: JZ-ZJ-001 + name: 调查终结报告文件校验 + desc: 若没有调查终结报告,则扣分 + risk: medium + score: 10 + scope: + - 案件调查终结报告 + stages: + - id: '1' + check: required + field: 案件调查终结报告.案由 + messages: + pass: 存在完整的调查终结报告。 + fail: 缺少调查终结报告,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + - rule_id: JZ-ZJ-002 + name: 案由、立案时间和当事人基本情况记载 + desc: 若当事人信息与提取出的信息不一致,则扣分。 + risk: medium + score: 5 + scope: + - 案件调查终结报告 + - 证据复制(提取)单 + stages: + - id: '1' + check: required + fields: + - 案件调查终结报告.案件来源 + - 案件调查终结报告.案由 + - 案件调查终结报告.立案日期 + - 案件调查终结报告.单位名称 + - 案件调查终结报告.单位法代 + - 案件调查终结报告.单位电话 + - 案件调查终结报告.单位地址 + - id: '2' + check: required + fields: + - 案件调查终结报告.案件来源 + - 案件调查终结报告.案由 + - 案件调查终结报告.立案日期 + - 案件调查终结报告.个人姓名 + - 案件调查终结报告.个人性别 + - 案件调查终结报告.个人年龄 + - 案件调查终结报告.个人民族 + - 案件调查终结报告.个人电话 + - 案件调查终结报告.个人证件 + - 案件调查终结报告.个人住址 + - id: '3' + check: match + pairs: + - source: 案件调查终结报告.单位名称 + target: 证据复制(提取)单.执照名称 + when: "当事人类型 != '个人'" + - source: 案件调查终结报告.单位法代 + target: 证据复制(提取)单.执照法代 + when: "当事人类型 != '个人'" + - source: 案件调查终结报告.单位地址 + target: 证据复制(提取)单.执照住所 + when: "当事人类型 != '个人'" + - id: '4' + check: match + pairs: + - source: 案件调查终结报告.个人姓名 + target: 证据复制(提取)单当事人.身份证姓名 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人性别 + target: 证据复制(提取)单当事人.身份证性别 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人民族 + target: 证据复制(提取)单当事人.身份证民族 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人住址 + target: 证据复制(提取)单当事人.身份证住址 + when: "当事人类型 != '单位'" + - source: 案件调查终结报告.个人证件 + target: 证据复制(提取)单当事人.身份证号 + when: "当事人类型 != '单位'" + logic: (1 AND 3) OR (2 AND 4) + messages: + pass: 当事人基本情况记载准确。请检查案后及时间是否正确。 + fail: 记载不准确或缺失,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + - rule_id: JZ-ZJ-003 + name: 当事人基本情况记载-一致 + desc: 检查调查终结报告中当事人基本信息与身份证信息是否一致 + risk: medium + score: 1 + scope: + - 案件调查终结报告 + - 证据复制(提取)单 + stages: + - id: '1' + check: match + pairs: + - source: 案件调查终结报告.个人姓名 + target: 证据复制(提取)单当事人.身份证姓名 + - source: 案件调查终结报告.个人性别 + target: 证据复制(提取)单当事人.身份证性别 + - source: 案件调查终结报告.个人民族 + target: 证据复制(提取)单当事人.身份证民族 + - source: 案件调查终结报告.个人住址 + target: 证据复制(提取)单当事人.身份证住址 + - source: 案件调查终结报告.个人证件 + target: 证据复制(提取)单当事人.身份证号 + messages: + pass: 文档检查通过,符合规范要求。 + fail: 文档存在以下问题,请修改后重新提交。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic + - rule_id: JZ-ZJ-004 + name: 案件调查终结报告承办人及承办部门负责人签字日期 + desc: 若没有承办人及承办人负责人签字、或者没有签字日期,则扣分。 + risk: medium + score: 5 + scope: + - 案件调查终结报告 + stages: + - id: '1' + check: required + fields: + - 案件调查终结报告.处理意见日期 + - 案件调查终结报告.处理意见承办人签名1 + - 案件调查终结报告.处理意见承办人签名2 + messages: + pass: 承办人及承办部门负责人已签字并签署日期。 + fail: 缺少签字或日期,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic +- group: JZG-CL + rules: + - rule_id: JZ-CL-001 + name: 法制部门或法制员意见明确性 + desc: 若法制部门意见栏无文字描述内容,则扣分。 + risk: medium + score: 10 + scope: + - 案件处理审批表 + stages: + - id: '1' + check: required + fields: + - 案件处理审批表.法制部门意见 + - 案件处理审批表.法制部门日期 + - 案件处理审批表.法制部门审核人签名 + - 案件处理审批表.法制部门负责人签名 + messages: + pass: 法制部门或法制员意见明确。 + fail: 法制部门或法制员意见缺失或不明确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十八条 + type: deterministic + - rule_id: JZ-CL-002 + name: 案件处理审批表承办人意见和签名 + desc: 若承办人意见栏中无文字内容或无签名日期,则扣分。 + risk: medium + score: 5 + scope: + - 案件处理审批表 + stages: + - id: '1' + check: required + fields: + - 案件处理审批表.承办人意见 + - 案件处理审批表.承办人日期 + - 案件处理审批表.承办部门意见 + - 案件处理审批表.承办部门日期 + - 案件处理审批表.承办部门签名 + - 案件处理审批表.承办人签名1 + - 案件处理审批表.承办人签名2 + messages: + pass: 承办人意见和签名完整。 + fail: 缺少承办人意见或签名,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十八条 + type: deterministic + - rule_id: JZ-CL-003 + name: 案件处理审批表负责人审批意见明确性 + desc: 检查案件处理审批表负责人审批意见内容和日期是否完整 + risk: medium + score: 10 + scope: + - 案件处理审批表 + stages: + - id: '1' + check: required + fields: + - 案件处理审批表.负责人日期 + - 案件处理审批表.负责人意见 + - 案件处理审批表.负责人签名 + messages: + pass: 行政机关负责人审批意见明确,签名和审批时间规范。 + fail: 审批意见不明确或签名审批时间不规范,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十七条 + type: deterministic +- group: JZG-ZG + rules: + - rule_id: JZ-ZG-001 + name: 行政处罚事先告知书送达 + desc: 若送达方式为"直接送达",则收件人签名或盖章栏无信息,则扣分。 若送达方式为"邮寄送达",则校验证据复制(提取)中是否有邮件回执,若不存在,则扣分。 + risk: medium + score: 10 + scope: + - 证据复制(提取)单 + - 送达回证 + stages: + - id: '1' + check: contains + field: 送达回证.送达方式 + value: 直接送达 + - id: '2' + check: contains + field: 送达回证.送达方式 + value: 邮寄送达 + - id: '3' + check: required + field: 证据复制(提取)单.邮件回执 + logic: 1 OR (2 AND 3) + messages: + pass: 事先告知书已送达当事人。 + fail: 事先告知书可能未送达当事人,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第六十一条 + type: deterministic +- group: JZG-ZX + rules: + - rule_id: JZ-ZX-001 + name: 罚款、没收违法所得处罚执行规范性 + desc: 若不存在《缴款凭证》(含《广东省非税收入一般缴款书(电子)》及其收款证明等任何形式的缴款凭证),则扣分。若缴款书中金额与处罚决定书中金额总计不一致,则扣分。 + risk: medium + score: 10 + scope: + - 处罚决定书 + - 缴款凭证 + stages: + - id: '1' + check: required + fields: + - 缴款凭证.金额 + - 缴款凭证.收入项目 + - 处罚决定书.罚款项目 + - 处罚决定书.罚款基数 + - 处罚决定书.罚款比例 + - 处罚决定书.罚款总额 + - id: '2' + check: ai + prompt: '请分析{{处罚决定书.罚款项目}}对应{{处罚决定书.罚款基数}}乘{{处罚决定书.罚款比例}},计算并校对与{{处罚决定书.罚款总额}}一致,同时{{处罚决定书.罚款总额}}与{{缴款凭证.金额}}需一致 + + ' + messages: + pass: 罚款、没收违法所得处罚已开具缴款书,有银行缴费收款证明,且与处罚决定书一致。 + fail: 未开具缴款书或无银行缴费证明,或与处罚决定书不一致,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第六十六条、第六十七条 + type: ai_rule + activate_if: 缴款凭证 != None + - rule_id: JZ-ZX-002 + name: 发还当事人物品与先行登记保存物品-一致 + desc: 若两份文件表格中,数量不一致,则涉案物品返还清单中备注一列需要有内容,没有内容则扣分。 + risk: medium + score: 10 + scope: + - 涉案物品返还清单 + - 证据先行登记保存批准书 + stages: + - id: '1' + check: ai + prompt: '{{证据先行登记保存批准书.表格品规}}和{{涉案物品返还清单.返还明细}}表格中的物品和数量应当一致,若 涉案物品返还清单表格中的具体的品种规格和数量行列数据不一致,则通过涉案物品返还清单的备注的内容进一步判断是否一致(即数量+损耗数量) + + ' + messages: + pass: 发还物品与先行登记保存物品一致,或不一致时已说明原因。 + fail: 发还物品与先行登记保存物品不一致且未说明原因,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: ai_rule + - rule_id: JZ-ZX-003 + name: 损耗费用返还合规性 + desc: 若签名或盖章不存在,或日期未填写,则扣分。 + risk: medium + score: 10 + scope: + - 卷宗封面 + - 涉案物品返还清单 + stages: + - id: '1' + check: contains + field: 卷宗封面.处理结果 + value: 销毁 + - id: '2' + check: required + field: 卷宗封面.处理结果 + - id: '3' + check: required + fields: + - 涉案物品返还清单.日期 + - 涉案物品返还清单.补偿信息 + - 涉案物品返还清单.返还确认 + - 涉案物品返还清单.接收人签名 + - id: '4' + check: required + fields: + - 涉案物品返还清单.日期 + - 涉案物品返还清单.接收单位印章 + - 涉案物品返还清单.补偿信息 + - 涉案物品返还清单.返还确认 + logic: (1 AND 2) OR ((NOT 1) AND 2 AND (3 OR 4)) + messages: + pass: 已全部返还留样卷烟或鉴别检验损耗费用。 + fail: 未全部返还,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十六条 + type: deterministic + activate_if: 涉案物品返还清单 != None or (卷宗封面 != None and 卷宗封面.处理结果 != None) + - rule_id: JZ-ZX-004 + name: 缴款凭证填写规范性 + desc: 若处罚中有没收而文件中不存在没收收据,则扣分。 + risk: medium + score: 5 + scope: + - 处罚决定书 + - 缴款凭证 + stages: + - id: '1' + check: required + fields: + - 处罚决定书.罚款说明 + - 缴款凭证.备注 + messages: + pass: 存在缴款凭证,请进一步确认填写是否规范。 + fail: 未找到缴款凭证,请核对文书是否齐全 + references_laws: + - 《中华人民共和国行政处罚法》第六十七条 + type: deterministic + activate_if: 缴款凭证 != None +- group: JZG-JA + rules: + - rule_id: JZ-JA-001 + name: 当事人名称、违法事实和处罚内容记载准确性 + desc: 若两份文书中的当事人名称不一致,则扣分。 + risk: medium + score: 10 + scope: + - 处罚决定书 + - 结案报告表 + stages: + - id: '1' + check: match + pairs: + - source: 结案报告表.当事人 + target: 处罚决定书.当事人 + messages: + pass: 当事人名称、处罚内容记载一致,请进一步检查违法事实是否一致。 + fail: 当事人记载不准确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十九条 + type: deterministic + - rule_id: JZ-JA-002 + name: 行政处罚决定的执行结果记载 + desc: 若执行情况栏后不存在描述内容,则扣分。 + risk: medium + score: 10 + scope: + - 结案报告表 + stages: + - id: '1' + check: required + field: 结案报告表.执行情况 + messages: + pass: 行政处罚决定的执行结果存在对应记载内容。 + fail: 执行结果记载不准确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第七十一条 + type: deterministic + - rule_id: JZ-JA-003 + name: 结案意见、签名及其时间填写规范性 + desc: 若承办人、承办机构负责人和办案单位负责人的意见、签名及其时间任意一项未找到,则扣分。 + risk: medium + score: 10 + scope: + - 结案报告表 + stages: + - id: '1' + check: required + fields: + - 结案报告表.承办人结案理由 + - 结案报告表.承办人结案日期 + - 结案报告表.承办部门意见 + - 结案报告表.承办部门日期 + - 结案报告表.负责人意见 + - 结案报告表.负责人日期 + - 结案报告表.负责人签名 + - 结案报告表.承办人结案签名1 + - 结案报告表.承办人结案签名2 + - 结案报告表.承办部门签名 + messages: + pass: 意见、签名及其时间填写规范。 + fail: 填写不规范,请核对并更正。 + references_laws: + - 《中华人民共和国行政处罚法》第五十四条 + type: deterministic + - rule_id: JZ-JA-004 + name: 结案后按期立卷归档 + desc: 通过AI检查结案后是否在10日内立卷归档 + risk: medium + score: 10 + scope: + - 卷内备考表 + - 结案报告表 + stages: + - id: '1' + check: ai + prompt: '请你判断{{卷内备考表.立卷时间}}与{{结案报告表.负责人日期}}是否相差小于10天 + + ' + messages: + pass: 结案后已按期立卷归档。 + fail: 结案后未按期立卷归档,请核对。 + references_laws: + - 《烟草专卖行政处罚程序规定》 + type: ai_rule diff --git a/387f06411f279cd1d2ea98aacc5a6c1f.png b/387f06411f279cd1d2ea98aacc5a6c1f.png new file mode 100644 index 0000000000000000000000000000000000000000..3bad85ab057e639eb060bf087ed18eebde5fe954 GIT binary patch literal 529016 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%0Dp=G)T>E-EPX@CN6 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%0ALEYT(`xdiT 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 -Fnjz`mj`2lq8##y=h27a+% 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

{~wT1||;&6X_Qt5*Mznsw>jFW)bp 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 z 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⋘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 + + + + + 评查详情纵向抽屉原型 + + + +

+ +
+ + +
+ + + + diff --git a/docs/superpowers/plans/2026-05-22-rag-dsl-bridge-merge.md b/docs/superpowers/plans/2026-05-22-rag-dsl-bridge-merge.md new file mode 100644 index 0000000..1fe6660 --- /dev/null +++ b/docs/superpowers/plans/2026-05-22-rag-dsl-bridge-merge.md @@ -0,0 +1,407 @@ +# RAG DSL Bridge Merge Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Safely bring `gitea/jande-feature-dsl` RAG-backed rule DSL execution into current `wren-dev` without overwriting tenant, permission, or page-quality work already present. + +**Architecture:** Add a shared `RagRetriever` service that both RAG chat and the leaudit evaluation pipeline can call. Wire the pipeline to pass a retriever into `leaudit.evaluate_extraction`, where the installed/local `leaudit` package already supports `stage.rag.query_template`. Keep current tenant-aware RAG chat code as the source of truth and only replace duplicate retrieval helpers with calls into the shared retriever. + +**Tech Stack:** Python 3.12, FastAPI, SQLAlchemy async sessions, Chroma, httpx, pytest, leaudit DSL/evaluation engine. + +--- + +## File Structure + +- Create `fastapi_modules/fastapi_leaudit/rag_engine/retriever.py`: shared RAG retrieval implementation copied from `gitea/jande-feature-dsl`, with vector search, keyword fallback, source filtering, document hydration, and source formatting. +- Modify `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py`: inject `RagRetriever` into `LauditPipeline` and pass it to `evaluate_extraction`. +- Modify `fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py`: preserve current tenant-aware chat API and delegate retrieval internals to `RagRetriever`. +- Modify `rules/行政处罚/rules.yaml`: append only the new `JZ-JD-005` RAG-backed rule from `gitea/jande-feature-dsl`; do not rewrite existing rules. +- Create `tests/test_rag_retriever.py`: validates vector retrieval source filtering and keyword fallback. +- Create `tests/test_leaudit_rag_bridge.py`: validates pipeline passes the injected retriever to leaudit evaluation. + +## Execution Constraints + +- Do not run `git merge gitea/jande-feature-dsl` in the working tree. +- Do not touch current untracked files unless explicitly requested. +- Do not overwrite `fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py`; it has unrelated page-quality work in progress. +- Stage and commit only after explicit user approval. +- If `ragChatServiceImpl.py` behavior changes beyond retrieval helper delegation, stop and re-review before continuing. + +### Task 1: Copy Shared Retriever And Tests + +**Files:** +- Create: `fastapi_modules/fastapi_leaudit/rag_engine/retriever.py` +- Create: `tests/test_rag_retriever.py` +- Create: `tests/test_leaudit_rag_bridge.py` + +- [ ] **Step 1: Restore files from source branch** + +Run: + +```bash +git checkout gitea/jande-feature-dsl -- fastapi_modules/fastapi_leaudit/rag_engine/retriever.py tests/test_rag_retriever.py tests/test_leaudit_rag_bridge.py +``` + +Expected: three files appear in working tree; no existing tenant code is modified. + +- [ ] **Step 2: Verify copied files are isolated** + +Run: + +```bash +git status --short fastapi_modules/fastapi_leaudit/rag_engine/retriever.py tests/test_rag_retriever.py tests/test_leaudit_rag_bridge.py +``` + +Expected: + +```text +A fastapi_modules/fastapi_leaudit/rag_engine/retriever.py +A tests/test_leaudit_rag_bridge.py +A tests/test_rag_retriever.py +``` + +### Task 2: Wire Retriever Into Pipeline + +**Files:** +- Modify: `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py` +- Test: `tests/test_leaudit_rag_bridge.py` + +- [ ] **Step 1: Inspect current pipeline imports and constructor** + +Run: + +```bash +sed -n '1,120p' fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py +``` + +Expected: confirm current imports include `StorageAdapter` and constructor currently has `ocr_client`, `llm_client`, `storage_adapter`. + +- [ ] **Step 2: Add retriever import** + +Add this import next to the existing platform imports: + +```python +from fastapi_modules.fastapi_leaudit.rag_engine.retriever import RagRetriever +``` + +- [ ] **Step 3: Extend constructor without changing existing arguments** + +Change constructor signature to include: + +```python + rag_retriever: RagRetriever | None = None, +``` + +Then initialize: + +```python + self.rag_retriever = rag_retriever or RagRetriever() +``` + +- [ ] **Step 4: Pass retriever to evaluation** + +In the `evaluate_extraction(...)` call, add: + +```python + retriever=self.rag_retriever, +``` + +Expected: this is a pure dependency-injection change; OCR, extraction, storage, and tenant behavior are unchanged. + +### Task 3: Preserve Tenant-Aware RAG Chat And Delegate Retrieval + +**Files:** +- Modify: `fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py` + +- [ ] **Step 1: Inspect current import area and constructor** + +Run: + +```bash +sed -n '1,110p' fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py +``` + +Expected: current file imports `build_openai_embeddings_url`, `get_chroma`, and `TenantResolver`; constructor initializes `self.TenantResolver`. + +- [ ] **Step 2: Update imports minimally** + +Remove unused direct retrieval imports after delegation: + +```python + build_openai_embeddings_url, +``` + +Remove: + +```python +from fastapi_modules.fastapi_leaudit.rag_engine.chroma_client import get_chroma +``` + +Add: + +```python +from fastapi_modules.fastapi_leaudit.rag_engine.retriever import RagRetriever +``` + +Keep: + +```python +from fastapi_modules.fastapi_leaudit.services.impl.tenantResolver import TenantResolver +``` + +- [ ] **Step 3: Preserve constructor and add retriever** + +Change constructor to: + +```python + def __init__(self, retriever: RagRetriever | None = None) -> None: + self.TenantResolver = TenantResolver() + self.retriever = retriever or RagRetriever() +``` + +Expected: existing tenant resolver remains active. + +- [ ] **Step 4: Replace `_retrieve_context` implementation only** + +Replace the body of `_retrieve_context` with: + +```python + result = await self.retriever.retrieve(query=query, dataset_id=dataset_id) + return result.chunks, result.dataset_name +``` + +Do not change method signature. + +- [ ] **Step 5: Delegate `_embed_texts`** + +Replace the body of `_embed_texts` with: + +```python + return await self.retriever._embed_texts(texts, model_name) +``` + +- [ ] **Step 6: Delegate keyword fallback helper** + +Replace the body of `_keyword_retrieve_context` with: + +```python + chunks = await self.retriever._keyword_retrieve_context( + dataset_id=dataset_id, + collection_name=collection_name, + dataset_name=dataset_name, + query=query, + top_k=top_k, + score_threshold=score_threshold, + source_names=None, + ) + return chunks[:top_k] +``` + +- [ ] **Step 7: Delegate keyword utility methods** + +Replace helper bodies: + +```python + def _build_keyword_terms(self, query: str) -> list[str]: + return self.retriever._build_keyword_terms(query) + + def _normalize_keyword_query(self, query: str) -> str: + return self.retriever._normalize_keyword_query(query) + + def _score_keyword_chunk(self, *, query: str, terms: list[str], content: str, document_name: str) -> float: + return self.retriever._score_keyword_chunk( + query=query, + terms=terms, + content=content, + document_name=document_name, + ) +``` + +- [ ] **Step 8: Delegate source building and hydration** + +Replace `_build_sources` body: + +```python + build_sources = getattr(self.retriever, "build_sources", None) + if callable(build_sources): + return build_sources(context_chunks, dataset_name) + return RagRetriever(hydrate_documents=False).build_sources(context_chunks, dataset_name) +``` + +Replace `_hydrate_document_hits` body: + +```python + return await self.retriever._hydrate_document_hits(dataset_id, chunks) +``` + +Expected: public chat behavior, tenant filtering, app resolution, session ownership, and permission feedback remain current `wren-dev` behavior. + +### Task 4: Append Administrative Penalty RAG Rule + +**Files:** +- Modify: `rules/行政处罚/rules.yaml` + +- [ ] **Step 1: Confirm new rule is not already present** + +Run: + +```bash +grep -n "JZ-JD-005" rules/行政处罚/rules.yaml +``` + +Expected: no output before insertion. + +- [ ] **Step 2: Append only the source-branch rule** + +Extract from `gitea/jande-feature-dsl` and insert the `JZ-JD-005` block after the existing `JZ-JD-004` rule in `rules/行政处罚/rules.yaml`. + +The inserted rule must include: + +```yaml + - rule_id: JZ-JD-005 + name: 案由及裁量标准适用准确性 + desc: 结合处罚决定书认定依据、处罚依据、罚款项目和罚款金额,检索案由与裁量标准,判断处罚种类和罚款幅度是否适用准确。 + risk: medium + score: 10 + scope: + - 处罚决定书 + rag: + collection: general_legal_kb + top_k: 5 + source_names: + - 广东省烟草专卖行政处罚裁量执行标准-rag.md + - 案由_行政处罚与反走私管理治理办法.md + query_template: | + 认定依据:{{处罚决定书.认定依据}} + 处罚依据:{{处罚决定书.处罚依据}} + 罚款项目:{{处罚决定书.罚款项目}} + 罚款基数:{{处罚决定书.罚款基数}} + 罚款比例:{{处罚决定书.罚款比例}} + 罚款总额:{{处罚决定书.罚款总额}} + 问题:检索对应案由、裁量档次、处罚种类和罚款幅度 + inject_as: rag_context + resources_as: rag_resources + stages: + - id: '1' + check: required + fields: + - 处罚决定书.认定依据 + - 处罚决定书.处罚依据 + - 处罚决定书.罚款项目 + - 处罚决定书.罚款基数 + - 处罚决定书.罚款比例 + - 处罚决定书.罚款总额 + - id: '2' + check: ai + prompt: | + 请结合检索到的法律知识和卷宗处罚决定书字段,判断案由、裁量档次、处罚种类和罚款幅度是否适用准确。 + + 【检索依据】 + {{rag_context}} + + 【处罚决定书字段】 + 认定依据:{{处罚决定书.认定依据}} + 处罚依据:{{处罚决定书.处罚依据}} + 罚款项目:{{处罚决定书.罚款项目}} + 罚款基数:{{处罚决定书.罚款基数}} + 罚款比例:{{处罚决定书.罚款比例}} + 罚款总额:{{处罚决定书.罚款总额}} + + 【判断要求】 + 1. 判断违法事实对应案由是否准确; + 2. 判断处罚依据是否能支撑对应处罚种类; + 3. 判断罚款基数、比例、总额是否落在裁量标准允许幅度内; + 4. 若检索依据不足以确认,应给出 warn,不要编造依据。 + logic: 1 AND 2 + messages: + pass: 案由、裁量档次、处罚种类和罚款幅度适用准确。 + fail: 案由、裁量档次、处罚种类或罚款幅度可能适用不准确,请核对。 + references_laws: + - 《中华人民共和国行政处罚法》第五十九条 + type: ai_rule +``` + +Expected: YAML diff only contains the new rule block. + +### Task 5: Verify Compile And Targeted Tests + +**Files:** +- Verify: `fastapi_modules/fastapi_leaudit/rag_engine/retriever.py` +- Verify: `fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py` +- Verify: `fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py` +- Verify: `tests/test_rag_retriever.py` +- Verify: `tests/test_leaudit_rag_bridge.py` + +- [ ] **Step 1: Run Python compile check** + +Run: + +```bash +.venv/bin/python -m py_compile fastapi_modules/fastapi_leaudit/rag_engine/retriever.py fastapi_modules/fastapi_leaudit/leaudit_bridge/pipeline.py fastapi_modules/fastapi_leaudit/services/impl/ragChatServiceImpl.py +``` + +Expected: exit code 0, no syntax errors. + +- [ ] **Step 2: Run targeted tests** + +Run: + +```bash +.venv/bin/pytest tests/test_rag_retriever.py tests/test_leaudit_rag_bridge.py -q +``` + +Expected: all tests pass. + +- [ ] **Step 3: Run current relevant RAG chat tests if present** + +Run: + +```bash +find tests -maxdepth 2 -type f -iname '*rag*chat*' -o -iname '*rag*permission*' +``` + +If files are found, run them with `.venv/bin/pytest -q`. Expected: pass or pre-existing unrelated failure documented. + +### Task 6: Final Diff Review + +**Files:** +- Review all touched files. + +- [ ] **Step 1: Show changed files** + +Run: + +```bash +git status --short +``` + +Expected: touched files include only the planned files plus pre-existing unrelated files. + +- [ ] **Step 2: Review diff summary** + +Run: + +```bash +git diff --stat +``` + +Expected: planned files dominate; no accidental frontend, database, or page-quality code changes except pre-existing `documentServiceImpl.py`. + +- [ ] **Step 3: Confirm no conflict markers** + +Run: + +```bash +grep -R "<<<<<<<\\|=======\\|>>>>>>>" -n fastapi_modules tests rules || true +``` + +Expected: no output. + +- [ ] **Step 4: Report status instead of committing** + +Do not commit automatically. Report: + +- Files changed. +- Tests run and result. +- Whether rules YAML needs OSS/database re-import to become active. +- Any known risk, especially dependency on installed `leaudit` package supporting `retriever`. diff --git a/docs/superpowers/plans/2026-05-22-route-permission-guard.md b/docs/superpowers/plans/2026-05-22-route-permission-guard.md new file mode 100644 index 0000000..a0d5756 --- /dev/null +++ b/docs/superpowers/plans/2026-05-22-route-permission-guard.md @@ -0,0 +1,171 @@ +# Route Permission Guard Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Prevent users from opening hidden/unauthorized frontend pages by manually entering URLs. + +**Architecture:** Keep backend API permission checks unchanged, and add a server-side Next.js page-route guard inside the authenticated `(audit)` layout. The guard uses backend user route authorization, normalizes feature subpages to their controlled route, and redirects unauthorized page requests before rendering content. + +**Tech Stack:** Next.js 15 App Router, TypeScript, Node test runner, existing RBAC `/api/rbac/user/routes` data. + +--- + +### Task 1: Add Route Access Unit Tests + +**Files:** +- Create: `legal-platform-frontend/lib/auth/route-access.ts` +- Test: `legal-platform-frontend/tests/govdoc-audit/route-access.test.mts` +- Modify: `legal-platform-frontend/lib/utils/route-alias.shared.js` + +- [ ] **Step 1: Write failing tests for direct URL authorization** + +Create tests that assert route guard behavior: + +```ts +import assert from "node:assert/strict"; +import test from "node:test"; + +import { isRoutePathAllowed, flattenMenuPaths } from "../../lib/auth/route-access.ts"; +import { normalizeRoutePathForPermission } from "../../lib/utils/route-alias.shared.js"; + +const allowedPaths = flattenMenuPaths([ + { id: "home", title: "系统概览", path: "/home", icon: "", order: 1 }, + { id: "rules", title: "规则管理", path: "/rules", icon: "", order: 2 }, + { id: "contract", title: "合同管理", path: "/contract-template", icon: "", order: 3, children: [ + { id: "contract-list", title: "模板列表", path: "/contract-template/list", icon: "", order: 1 }, + ] }, +]); + +test("route guard allows exact authorized route", () => { + assert.equal(isRoutePathAllowed("/rules", allowedPaths), true); +}); + +test("route guard allows feature detail page through alias", () => { + assert.equal(isRoutePathAllowed("/rules-test/detail?packId=3&ruleId=MM-ENT-001", allowedPaths), true); +}); + +test("route guard rejects direct URL when route is hidden from role", () => { + assert.equal(isRoutePathAllowed("/tenants", allowedPaths), false); +}); + +test("route guard maps current govdoc pages to govdoc root permission", () => { + assert.equal(normalizeRoutePathForPermission("/govdoc/audits"), "/govdoc"); + assert.equal(normalizeRoutePathForPermission("/govdoc/detail/A-108bce03"), "/govdoc"); +}); +``` + +- [ ] **Step 2: Run tests and verify failure** + +Run: + +```bash +cd legal-platform-frontend +node --experimental-strip-types --test tests/govdoc-audit/route-access.test.mts +``` + +Expected: fail because `route-access.ts` does not exist yet and `/govdoc/*` is not normalized. + +### Task 2: Implement Pure Route Access Helper + +**Files:** +- Create: `legal-platform-frontend/lib/auth/route-access.ts` +- Modify: `legal-platform-frontend/lib/utils/route-alias.shared.js` + +- [ ] **Step 1: Implement helper** + +Add functions: +- `flattenMenuPaths(menuItems)` to extract authorized paths from route tree. +- `normalizeRequestPath(pathname)` to strip query/hash/trailing slash and apply aliases. +- `isRoutePathAllowed(pathname, allowedPaths)` to allow exact authorized routes, authorized route subtrees, and `/home`. + +- [ ] **Step 2: Add `/govdoc/*` route alias** + +Map current internal document pages to `/govdoc`, matching the existing legacy `/govdoc-audit/*` behavior. + +- [ ] **Step 3: Run focused tests** + +Run: + +```bash +cd legal-platform-frontend +node --experimental-strip-types --test tests/govdoc-audit/route-access.test.mts tests/govdoc-audit/home-routing.test.mts +``` + +Expected: all tests pass. + +### Task 3: Wire Server-Side Guard Into Authenticated Layout + +**Files:** +- Modify: `legal-platform-frontend/app/(audit)/layout.tsx` + +- [ ] **Step 1: Read current pathname** + +Use `headers().get("x-pathname")`, which is already set by `middleware.ts`. + +- [ ] **Step 2: Fetch user authorized routes** + +Call `getUserRoutesByRole(userRole, frontendJWT, true)` from server layout. + +- [ ] **Step 3: Redirect unauthorized pages** + +If routes load successfully and `isRoutePathAllowed(pathname, flattenMenuPaths(routes))` is false, redirect to: + +```ts +/home?error=insufficient_permissions +``` + +Do not block `/home`. + +- [ ] **Step 4: Fail closed when routes cannot load** + +If route loading fails because the session is expired, redirect to login. For non-auth failures, redirect to `/home?error=permission_check_failed` except when already on `/home`. + +### Task 4: Verify Build and Regression + +**Files:** +- No new production files unless tests expose type issues. + +- [ ] **Step 1: Run focused tests** + +```bash +cd legal-platform-frontend +node --experimental-strip-types --test tests/govdoc-audit/route-access.test.mts tests/govdoc-audit/home-routing.test.mts +``` + +- [ ] **Step 2: Run full existing frontend node tests** + +```bash +cd legal-platform-frontend +node --experimental-strip-types --test tests/govdoc-audit/*.test.mts +``` + +- [ ] **Step 3: Run lint** + +```bash +cd legal-platform-frontend +npm run lint -- --quiet +``` + +- [ ] **Step 4: Run production build** + +```bash +cd legal-platform-frontend +npm run build +``` + +### Task 5: Manual Acceptance Checklist + +- [ ] A role without `/tenants` cannot open `/tenants` by URL. +- [ ] A role without `/rules` cannot open `/rules-test/list` or `/rules-test/detail?...` by URL. +- [ ] A role with `/rules` can still open `/rules-test/list` and `/rules-test/detail?...`. +- [ ] `/home` remains reachable for logged-in users. +- [ ] Sidebar menu hiding remains unchanged. +- [ ] Backend API 403 behavior remains independent. + +--- + +### Self-Review + +- Spec coverage: Direct URL access is blocked at the server layout before page render. +- Placeholder scan: No TBD/TODO remains in implementation steps. +- Type consistency: Helper consumes existing `MenuItem` shape from `lib/auth/user-routes.ts`. diff --git a/docs/superpowers/plans/2026-05-23-business-entry-ux-optimization.md b/docs/superpowers/plans/2026-05-23-business-entry-ux-optimization.md new file mode 100644 index 0000000..e2e99f8 --- /dev/null +++ b/docs/superpowers/plans/2026-05-23-business-entry-ux-optimization.md @@ -0,0 +1,652 @@ +# 业务入口与业务类型交互优化实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 把当前“入口模块管理 + 文档类型管理 + 规则分组 + 上传”的用户理解成本降下来,让用户按“业务入口、业务大类、业务类型、规则”完成配置,而不是理解 `entry_module_id/type_id/group_id`。 + +**Architecture:** 不改后端核心数据模型,不自动创建业务大类或业务类型。前端做语义重构和交互包装:入口模块页只选择已有业务范围;业务类型管理页负责维护大类/类型;上传页保留两级选择但改成业务语言;规则分组页继续承接规则绑定。 + +**Tech Stack:** Next.js App Router、React、现有 `Card/Button/FormSelect/Table/Toast` 组件、现有 CSS 变量、FastAPI 现有入口模块/文档类型/规则分组接口、Playwright UI 验收。 + +--- + +## 一、设计结论 + +### 1.1 用户语义 + +统一使用下面这套用户可理解的语言: + +```text +业务入口 = 首页工作台,对应 leaudit_entry_modules +业务大类 = 上传第一步选择,对应一级分组/当前文档类型大类 +业务类型 = 上传第二步选择,对应二级分组/运行子类型 +规则配置 = 给业务类型绑定规则集 +``` + +前端不再重点暴露这些技术词: + +```text +入口模块绑定文档类型 +一级分组 +二级分组 +document_type_id +group_id +entry_module_id +``` + +技术词可以保留在调试信息、接口字段、开发文档里,但不能作为普通后台用户的主要操作语言。 + +### 1.2 业务边界 + +入口模块新建/编辑页只允许选择已有业务范围: + +```text +不能在入口模块页自动创建业务大类 +不能在入口模块页自动创建业务类型 +不能在入口模块页自动创建规则绑定 +``` + +如果用户找不到业务类型,页面只做引导: + +```text +未找到需要的业务类型?请先到“业务类型管理”维护。 +``` + +### 1.3 最终操作链路 + +```text +1. 业务类型管理:维护业务大类和业务类型 +2. 业务入口管理:创建入口,选择菜单、租户、业务范围 +3. 规则配置:给业务类型绑定规则集 +4. 上传页:选择业务大类、业务类型,上传文件 +5. 文档列表/评查:按入口、租户、大类、类型过滤和命中规则 +``` + +## 二、UI 风格约束 + +所有新增 UI 必须和当前系统保持一致: + +```text +继续使用现有 Card、Button、FormSelect、Table、Toast +继续使用现有 ant-btn / ant-btn-primary 按钮风格 +继续使用绿色主色 #00684a +继续使用 var(--color-primary-text)、var(--color-primary-text-muted)、var(--color-primary-border-soft)、var(--color-primary-surface) +继续使用当前后台页面 24px 外边距、Card 容器、表格、圆角、阴影风格 +继续沿用当前入口模块、文档类型、规则分组页面的表单布局 +``` + +禁止: + +```text +不要引入新的 UI 框架 +不要重做视觉体系 +不要大面积渐变、特殊字体、花哨动效 +不要把入口模块管理页做成和系统其他管理页不一致的风格 +不要改变现有按钮颜色体系 +``` + +## 三、页面信息架构调整 + +### 3.1 菜单命名 + +建议调整左侧菜单文案: + +```text +文档类型 -> 业务类型 +入口模块 -> 业务入口 +规则分组 -> 规则配置 +``` + +如果担心一次改名影响用户习惯,可以第一阶段使用过渡文案: + +```text +业务类型(原文档类型) +业务入口(原入口模块) +规则配置 +``` + +### 3.2 页面职责 + +```text +业务入口管理:配置工作台、菜单、租户、业务范围 +业务类型管理:维护业务大类和业务类型,不绑定规则集 +规则配置:给业务类型绑定规则集 +上传文档:选择业务大类和业务类型后上传 +``` + +## 四、入口模块管理 UI 方案 + +### 4.1 列表页优化 + +文件: + +```text +legal-platform-frontend/app/(audit)/entry-modules/EntryModulesClient.tsx +legal-platform-frontend/styles/pages/entry-modules.css +``` + +列表页保留现有表格风格,但字段改成业务可读: + +```text +入口名称 +工作台类型 +适用租户 +业务范围 +功能菜单 +状态 +操作 +``` + +业务范围列显示摘要: + +```text +合同 3 个类型 / 公文 2 个类型 +``` + +如果接口暂时没有业务范围摘要,第一阶段先显示: + +```text +已配置业务范围 +未配置业务范围 +``` + +操作按钮: + +```text +编辑入口 +配置业务范围 +预览入口 +删除/停用 +``` + +权限仍走现有 RBAC: + +```text +entry_module:list:read +entry_module:create:write +entry_module:update:write +entry_module:delete:delete +entry_module:image:write +``` + +### 4.2 新建/编辑页改成 4 步向导 + +文件: + +```text +legal-platform-frontend/app/(audit)/entry-modules/new/EntryModuleNewClient.tsx +legal-platform-frontend/styles/pages/entry-modules.css +``` + +页面顶部增加步骤条: + +```text +1 基础信息 -> 2 功能菜单 -> 3 适用租户 -> 4 业务范围 +``` + +步骤条只控制页面分区滚动/显示,不做复杂路由拆分。保存仍然是一个表单整体提交。 + +#### Step 1 基础信息 + +字段: + +```text +入口名称 +入口描述 +Logo +跳转入口 +``` + +跳转入口不要直接展示裸路径作为主选项,改成业务文案: + +```text +通用文档评查(/documents) +内部公文评查(/govdoc/audits) +交叉评查(/cross-checking) +``` + +保存时仍提交原 `route_path`。 + +#### Step 2 功能菜单 + +把菜单模板做成当前系统风格的轻量卡片: + +```text +通用文档评查 +合同工作台 +公文工作台 +交叉评查 +自定义工作台 +``` + +选中模板后自动带出默认功能。 + +功能勾选默认折叠为“高级功能设置”,避免用户一进来看到一大堆 checkbox。 + +高级区域展开后显示现有功能勾选: + +```text +首页 +文件上传 +文档列表 +规则管理 +规则分组 +模板搜索 +模板列表 +公文列表 +公文上传 +交叉评查 +创建任务 +评查任务列表 +使用统计 +``` + +#### Step 3 适用租户 + +保持 checkbox,但分组显示: + +```text +公共 + PUBLIC + +地区租户 + 云浮 + 揭阳 + 梅州 +``` + +提示文案: + +```text +未勾选的租户首页不会看到该业务入口。 +``` + +#### Step 4 业务范围 + +标题: + +```text +这个入口可以处理哪些业务? +``` + +交互: + +```text +[ ] 合同 + [ ] 建设工程合同 + [ ] 买卖合同 + [ ] 租赁合同 + +[ ] 公文 + [ ] 请示 + [ ] 通知 + [ ] 会议纪要 +``` + +规则: + +```text +勾选业务大类 = 勾选其下全部业务类型 +取消某个业务类型 = 当前入口不包含这个类型 +只允许选择已有业务大类和业务类型 +不自动创建业务大类和业务类型 +``` + +右侧摘要: + +```text +已选择 2 个业务大类,5 个业务类型 +上传页将只显示这些业务范围 +文档列表将只显示这些业务范围 +规则配置将只显示这些业务范围 +``` + +空状态: + +```text +暂无可选业务类型 +请先到“业务类型管理”维护业务大类和业务类型 +[去业务类型管理] +``` + +### 4.3 业务范围接口策略 + +第一阶段优先复用现有接口: + +```text +GET /api/v3/document-type-roots?entry_module_id=... +GET /api/evaluation-point-groups?entry_module_id=... +GET /api/evaluation-point-groups/by-document-types +``` + +如果现有接口难以一次返回完整树,再新增轻量聚合接口: + +```text +GET /api/entry-modules/{id}/business-scope-options +PUT /api/entry-modules/{id}/business-scope +``` + +返回结构建议: + +```json +{ + "roots": [ + { + "id": 1, + "name": "合同", + "code": "root.contract", + "selected": true, + "children": [ + { + "groupId": 101, + "documentTypeId": 11, + "name": "建设工程合同", + "code": "contract.construction", + "selected": true + } + ] + } + ] +} +``` + +保存结构建议: + +```json +{ + "selectedGroupIds": [101, 102, 201] +} +``` + +注意: + +```text +这里保存的是入口可用业务范围,不创建新业务类型。 +``` + +## 五、业务类型管理 UI 方案 + +### 5.1 页面改名和说明 + +文件: + +```text +legal-platform-frontend/app/(audit)/document-types/DocumentTypesIndexClient.tsx +legal-platform-frontend/app/(audit)/document-types/new/DocumentTypesNewClient.tsx +legal-platform-frontend/styles/pages/document-types_index.css +legal-platform-frontend/styles/pages/document-types_new.css +``` + +页面标题: + +```text +业务类型管理 +``` + +顶部说明: + +```text +这里维护系统可用的业务大类和业务类型。 +业务大类用于上传时第一步选择。 +业务类型用于上传时第二步选择,并用于绑定规则集。 +``` + +### 5.2 列表页展示 + +当前表格保留,但列名改成: + +```text +编码 +业务大类 +所属业务入口 +业务类型数量 +已绑定规则集 +状态 +操作 +``` + +“一级文档类型”“一级分组”“二级分组”这些词从主表格文案里去掉。 + +### 5.3 新建/编辑页文案 + +当前页先只维护业务大类,不让用户误会它会自动创建运行类型。 + +标题: + +```text +新建业务大类 +编辑业务大类 +``` + +说明: + +```text +业务大类是上传时第一步选择,例如合同、公文、案卷。具体业务类型请在规则配置中维护。 +``` + +如果后续要把业务类型维护也放到这里,需要单独设计二级列表,不和本轮混在一起。 + +## 六、上传页 UI 方案 + +文件: + +```text +legal-platform-frontend/app/(audit)/files/upload/FilesUploadClient.tsx +legal-platform-frontend/styles/pages/files_upload.css +``` + +上传页保留两级选择,但统一文案: + +```text +业务大类 +业务类型 +``` + +选择逻辑: + +```text +先按当前入口模块过滤业务大类 +选择业务大类后,只显示当前入口允许的业务类型 +``` + +默认规则: + +```text +当前入口只有一个业务大类 -> 默认选中并展示提示 +当前业务大类只有一个业务类型 -> 默认选中并展示提示 +``` + +提示: + +```text +当前业务入口:合同评查 +上传文件将归属到所选业务大类和业务类型。 +``` + +提交字段不变: + +```text +entryModuleId +typeId +groupId +tenantCode +``` + +## 七、规则配置页 UI 方案 + +文件: + +```text +legal-platform-frontend/app/(audit)/rule-groups/RuleGroupsClient.tsx +legal-platform-frontend/styles/pages/rule-groups_index.css +``` + +文案调整: + +```text +规则分组 -> 规则配置 +一级分组 -> 业务大类 +二级分组 -> 业务类型 +绑定规则集 -> 配置评查规则 +``` + +操作规则不变: + +```text +业务大类不能绑定规则集 +业务类型才可以绑定规则集 +``` + +按钮文案: + +```text +新增一级分组 -> 新增业务大类 +新增二级分组 -> 新增业务类型 +绑定规则集 -> 配置规则 +``` + +## 八、实施任务清单 + +### 8.1 准备和基线 + +- [x] 执行 `./leaudit.sh status`,确认后端、前端、Worker、Beat 运行。 +- [ ] 使用 Playwright 登录 `000/admin06111` 截取当前入口模块、文档类型、上传、规则分组页面现状。 +- [ ] 记录当前主要入口 URL:`/entry-modules`、`/entry-modules/new`、`/document-types`、`/files/upload`、`/rule-groups`。 + +### 8.2 入口模块列表页优化 + +- [x] 修改 `EntryModulesClient.tsx` 页面标题和文案:`入口模块管理` 改为 `业务入口管理`。 +- [x] 修改列表列名,隐藏或弱化技术字段。 +- [x] 增加功能菜单摘要展示,沿用现有 tag/badge 风格。 +- [x] 增加业务范围摘要占位,接口未完成前显示 `待配置` 或 `已配置`。 +- [ ] 跑 Playwright 验证列表页没有布局溢出,按钮权限仍正确。 + +### 8.3 入口模块新建/编辑页 4 步向导 + +- [x] 在 `EntryModuleNewClient.tsx` 增加步骤条状态。 +- [x] 把现有基础字段移动到 `基础信息` 分区。 +- [x] 把 `route_path` 下拉改成业务文案 + 路径说明。 +- [x] 把菜单模板改成模板卡片,选中后仍更新 `menu_profile/features`。 +- [x] 把功能勾选移动到 `高级功能设置` 折叠区。 +- [x] 把租户勾选拆成 `公共` 和 `地区租户` 两组。 +- [x] 增加 `业务范围` 分区,先展示只读/占位状态和跳转 `业务类型管理` 按钮。 +- [x] 保持提交 payload 字段不变:`name/description/route_path/menu_profile/features/tenants`。 +- [x] 跑 TypeScript 检查。 +- [ ] 跑 Playwright 验证新建、编辑、权限只读、Logo 上传入口不破坏。 + +### 8.4 业务范围选择器接入 + +- [x] 新增前端组件 `BusinessScopeSelector`,放在入口模块页面附近,复用现有 checkbox、Card、empty state 风格。 +- [x] 优先用现有文档类型/规则分组接口组装业务大类和业务类型树。 +- [ ] 如果现有接口不足,补后端聚合接口 `business-scope-options`。 +- [x] 选择器支持勾选大类自动勾选子类型。 +- [x] 选择器支持右侧摘要:大类数、业务类型数。 +- [x] 保存时只保存已有业务类型范围,不创建新大类/类型。 +- [ ] 跑 Playwright 验证入口编辑页业务范围选择、保存、回显。 + +### 8.5 业务类型管理文案优化 + +- [x] 修改 `DocumentTypesIndexClient.tsx` 标题为 `业务大类管理`。 +- [x] 修改表格列名:业务大类、所属业务入口、业务类型数量、已绑定规则集。 +- [x] 修改空状态文案。 +- [x] 修改 `DocumentTypesNewClient.tsx` 标题为 `新建业务大类/编辑业务大类`。 +- [x] 修改说明文案,强调这里维护上传第一步的业务大类。 +- [x] 修改 `document-types/page.tsx` 和 `document-types/new/page.tsx` metadata,避免浏览器标题继续显示文档类型。 +- [x] 修改面包屑 `文档类型管理/新建文档类型` 为 `业务大类管理/新建业务大类`。 +- [x] 修改侧栏 fallback 菜单 `文档类型` 为 `业务大类管理`。 +- [x] 修改上传失败诊断文案中的 `文档类型管理/当前文档类型` 为 `业务大类管理/当前业务大类`。 +- [x] 保持现有创建/编辑接口字段不变。 +- [ ] 跑 Playwright 验证新建和编辑页字段仍能保存。 + +### 8.6 上传页交互文案优化 + +- [x] 修改上传页选择项文案:`文档类型` 改为 `业务大类`。 +- [x] 修改子类型选择项文案:`子类型/二级分组` 改为 `业务类型`。 +- [x] 当前入口只有一个业务大类时自动选中并展示提示。 +- [x] 当前业务大类只有一个业务类型时自动选中并展示提示。 +- [x] 保持提交字段 `entryModuleId/typeId/groupId/tenantCode` 不变。 +- [ ] 跑 Playwright 真实上传表单测试,确认字段落库正确。 + +### 8.7 规则配置页文案优化 + +- [x] 修改页面标题:`规则分组` 改为 `规则配置`。 +- [x] 修改树节点文案:一级分组显示为业务大类,二级分组显示为业务类型。 +- [x] 修改按钮文案:新增业务大类、新增业务类型、配置规则。 +- [x] 一级节点不显示配置规则入口。 +- [x] 二级节点显示配置规则入口。 +- [x] 跑 Playwright 验证规则配置页业务文案、业务大类/业务类型行展示和二级配置入口可见。 + +### 8.8 权限和多租户回归 + +- [ ] 验证没有 `entry_module:list:read` 不显示业务入口管理菜单。 +- [ ] 验证没有 `entry_module:create:write` 不显示新建业务入口按钮。 +- [ ] 验证没有 `entry_module:update:write` 编辑页不可保存业务入口。 +- [ ] 验证没有 `entry_module:image:write` 不可上传入口 Logo。 +- [ ] 验证云浮、揭阳、梅州租户只看到自己或 `PUBLIC` 入口。 + +### 8.9 最终验收 + +- [x] `legal-platform-frontend` 下运行 `npx tsc --noEmit --pretty false`。 +- [x] 运行目标 eslint,要求 `0 error`。 +- [x] 使用 Playwright 跑入口模块编辑页:业务范围步骤、业务范围摘要、业务大类列表/空状态回显。 +- [ ] 使用 Playwright 跑上传页:业务大类、业务类型选择和真实提交。 +- [x] 使用 Playwright 跑规则配置页:业务大类/业务类型树、一级不显示配置入口、二级显示配置入口。 +- [ ] 更新 `docs/superpowers/plans/2026-05-23-entry-module-menu-profile-multitenant-refactor.md` 执行记录。 + +### 8.10 执行记录 2026-05-23 + +- [x] 新增业务入口 UI helper:`legal-platform-frontend/lib/business-entry/business-entry-ui.ts`,统一维护工作台入口文案、菜单模板文案、功能菜单摘要。 +- [x] 新增单测:`legal-platform-frontend/tests/govdoc-audit/business-entry-ui.test.mts`,覆盖路由业务文案、模板文案、功能摘要。 +- [x] 使用 TDD 跑红灯:helper 缺失时测试失败,随后实现 helper 并通过。 +- [x] 优化业务入口列表页:标题、说明、列名、工作台入口、工作台类型、业务范围占位、功能菜单摘要改为业务语义。 +- [x] 列表页 Logo 预览从 `` 改为 `next/image`,目标 eslint 无 warning。 +- [x] 优化业务入口新建/编辑页:增加 `基础信息/功能菜单/适用租户/业务范围` 四步结构。 +- [x] 工作台入口下拉改为 `通用文档评查/内部公文评查/交叉评查`,保存仍使用原始 `route_path`。 +- [x] 菜单模板改为卡片选择,功能勾选移动到 `高级功能设置` 折叠区域。 +- [x] 租户选择拆成 `公共` 和 `地区租户` 两组。 +- [x] 业务范围先做占位和跳转 `业务类型管理`,不自动创建、不保存业务范围,避免破坏现有接口。 +- [x] 验证:`node --test --experimental-strip-types tests/govdoc-audit/business-entry-ui.test.mts` 结果 `5 pass / 0 fail`。 +- [x] 验证:目标 eslint 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 新增业务分类 UI helper:`legal-platform-frontend/lib/business-entry/business-taxonomy-ui.ts`,统一维护 `业务大类/业务类型` 标签和上传必填提示。 +- [x] 新增单测:`legal-platform-frontend/tests/govdoc-audit/business-taxonomy-ui.test.mts`,覆盖业务大类/业务类型文案。 +- [x] 优化业务类型管理列表页:标题、说明、列名、空状态统一为业务语义。 +- [x] 优化业务大类新建/编辑页:把 `一级文档类型/入口模块/二级分组/评查点分组` 主文案替换为 `业务大类/业务入口/业务类型/规则配置`。 +- [x] 优化上传页:选择卡片改为 `选择业务范围`,两级选择改为 `业务大类/业务类型`,错误提示和说明同步改为业务语义。 +- [x] 验证:`node --test --experimental-strip-types tests/govdoc-audit/business-taxonomy-ui.test.mts tests/govdoc-audit/business-entry-ui.test.mts` 结果 `7 pass / 0 fail`。 +- [x] 验证:业务类型管理和上传页目标 eslint 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 优化规则配置页:页面标题、指标卡、说明条、筛选项、业务大类/业务类型树、配置弹窗、删除确认和 toast 统一改成业务语义。 +- [x] 规则配置页保持接口和 payload 不变,仅替换用户可见文案;业务大类仍不显示配置规则入口,业务类型显示 `配置规则`。 +- [x] 修复规则配置页目标 eslint 的 hook dependency warning:把规则预览加载改为稳定 `useCallback` + ref 读取状态。 +- [x] 验证:`npx eslint app/\(audit\)/rule-groups/RuleGroupsClient.tsx --max-warnings=0` 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 新增业务范围 helper:`legal-platform-frontend/lib/business-entry/business-scope-ui.ts`,覆盖选择摘要和保存差异计算。 +- [x] 新增业务范围 API 封装:复用 `GET /api/v3/document-type-roots`、`GET /api/rule-groups/tree`、`PUT /api/v3/document-type-roots/{id}`。 +- [x] 入口模块新建/编辑页接入业务范围选择器:用户勾选业务大类,下属业务类型只读展示;保存只更新业务大类归属,不自动创建业务大类或业务类型。 +- [x] 验证:`node --test --experimental-strip-types tests/business-entry/business-scope-ui.test.mts tests/govdoc-audit/business-taxonomy-ui.test.mts tests/govdoc-audit/business-entry-ui.test.mts` 结果 `9 pass / 0 fail`。 +- [x] 验证:`npx eslint app/\(audit\)/entry-modules/new/EntryModuleNewClient.tsx lib/business-entry/business-scope-ui.ts --max-warnings=0` 结果 `0 error / 0 warning`。 +- [x] 验证:`npx eslint lib/api/legacy/entry-modules/business-scope.ts --no-warn-ignored --max-warnings=0` 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 修正遗漏的文档类型管理外露文案:页面 metadata、面包屑、侧栏 fallback、上传失败诊断统一改成 `业务大类管理/新建业务大类/业务大类`。 +- [x] 新增面包屑回归测试:`business category management breadcrumb uses business wording`。 +- [x] 验证:`node --test --experimental-strip-types tests/govdoc-audit/home-routing.test.mts tests/govdoc-audit/business-taxonomy-ui.test.mts` 结果 `12 pass / 0 fail`。 +- [x] 验证:目标 eslint 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 定位并修复 `/rule-groups` 服务端路由守卫误拦截:后端 RBAC 权限树当前返回 `/rules` 且聚合了 `evaluation_group:*` 权限,但未返回 `/rule-groups` 路由;布局只按 route path 放行导致跳转 `/home?error=insufficient_permissions`。 +- [x] 新增 `isRouteAllowedByBusinessPermission`:仅当访问 `/rule-groups` 且用户拥有 `evaluation_group:*` 权限时放行,避免扩大其他路由访问范围。 +- [x] 新增路由守卫单测:`route guard allows rule configuration when user has evaluation group permissions`,先红灯后实现,最终通过。 +- [x] Playwright 真实账号 `000/admin06111` 验收:`node /tmp/leaudit-business-entry-ux-smoke.js` 通过,结果 `scopeItems=38 / rootRows=37 / childRows=58 / errorCount=0`。 +- [x] 验证:`node --test --experimental-strip-types tests/business-entry/business-scope-ui.test.mts tests/govdoc-audit/business-taxonomy-ui.test.mts tests/govdoc-audit/business-entry-ui.test.mts tests/govdoc-audit/route-access.test.mts` 结果 `16 pass / 0 fail`。 +- [x] 验证:`npx eslint app/\(audit\)/layout.tsx lib/auth/route-access.ts tests/govdoc-audit/route-access.test.mts app/\(audit\)/entry-modules/new/EntryModuleNewClient.tsx app/\(audit\)/rule-groups/RuleGroupsClient.tsx lib/business-entry/business-scope-ui.ts --max-warnings=0` 结果 `0 error / 0 warning`。 +- [x] 验证:`npx tsc --noEmit --pretty false` 通过。 +- [x] 环境说明:本轮 `./leaudit.sh start/restart` 在当前工具会话里出现启动后进程立即消失的现象;为完成 Playwright 验收,临时用同等命令在 PTY 会话中启动后端 `.venv/bin/python run.py` 和前端 `npm run dev:dev`。 + +## 九、风险控制 + +- [ ] 第一阶段优先改文案和页面组织,不改数据库。 +- [ ] 入口模块页不自动创建业务大类/业务类型,避免隐式脏数据。 +- [ ] 上传页保留两级选择,避免用户传错类型。 +- [ ] 所有菜单生成仍经过 RBAC 权限过滤。 +- [ ] 所有入口范围仍经过租户过滤。 +- [ ] Playwright 真实验收前先完成 UI 交互优化,避免测试脚本固化错误交互。 diff --git a/docs/superpowers/plans/2026-05-23-entry-module-menu-profile-multitenant-refactor.md b/docs/superpowers/plans/2026-05-23-entry-module-menu-profile-multitenant-refactor.md new file mode 100644 index 0000000..e9626b7 --- /dev/null +++ b/docs/superpowers/plans/2026-05-23-entry-module-menu-profile-multitenant-refactor.md @@ -0,0 +1,2224 @@ +# 入口模块菜单配置与多租户重构实施计划 + +> **给后续执行开发的人:** 按本文任务逐步实施,不要跳着改。本文只做入口模块、菜单、文档归属、多租户范围的重构计划,不直接改动运行时规则评查逻辑。 + +**目标:** 让“入口模块”真正成为用户能理解的业务工作台,菜单显示、文档过滤、上传范围、规则分组、租户可见性都从入口模块配置出发,不再依赖“名称里是否包含合同/公文”这种硬编码判断。 + +**总体架构:** 保留 `leaudit_entry_modules` 作为首页入口模块主表,保留现有 `leaudit_entry_module_tenants` 作为租户可见性关系表。在入口模块上增加“菜单模板字段”`menu_profile` 和“功能清单字段”`features`,用它们决定该入口模块显示哪些功能菜单。角色权限系统继续负责页面和接口权限,入口模块只负责“业务工作台编排”和“业务范围”。 + +**涉及技术:** 后端接口、数据库原生查询、数据库迁移脚本、前端页面、前端侧边栏、现有角色权限系统、现有租户识别逻辑。 + +--- + +## 一、当前根因 + +现在系统的问题不是用户没配置好,而是代码在“猜业务类型”。 + +当前错误判断包括: + +- 合同菜单靠“入口模块名称里有没有合同两个字”判断。 +- 公文菜单靠“入口模块名称里有没有公文两个字”或固定路径判断。 +- 公文列表页面强行显示成“内部公文”。 +- 公文列表页面虽然读取了浏览器地址里的 `entryModuleId`,但没有传给后端列表接口。 +- 文档列表和规则页面部分支持 `entryModuleId`,但侧边栏菜单不认它。 +- 租户可见性已经有 `leaudit_entry_module_tenants`,但菜单功能没有和入口模块、租户上下文形成闭环。 + +目标链路应该变成: + +```text +当前用户租户 -> 可见入口模块 -> 用户选择入口模块 +入口模块 -> 菜单模板字段/功能清单字段 -> 生成左侧菜单 +入口模块 -> 文档类型 -> 上传/列表/规则分组范围 +文档 -> entry_module_id + type_id + group_id + tenant_code -> 后续评查/统计/列表过滤 +``` + +## 二、用户应该怎么理解 + +管理员配置入口模块时,只需要按业务语言操作: + +1. 新建入口模块,例如 `入口模块-测试`。 +2. 选择菜单模板:合同工作台、公文工作台、交叉评查工作台、通用文档评查、自定义。 +3. 勾选功能:文档列表、文件上传、规则配置、规则分组、模板搜索、模板列表、公文列表、公文上传等。 +4. 分配租户:云浮、揭阳、梅州、公共资源域等。 +5. 绑定一级文档类型。 +6. 在规则分组里配置二级运行子类型和规则绑定。 + +用户不应该被迫把入口模块命名为“合同xxx”或“公文xxx”才能显示对应功能。 + +## 三、核心数据模型 + +### 3.1 保留现有表 + +继续使用: + +- `leaudit_entry_modules`:入口模块主表,表示首页业务入口。 +- `leaudit_entry_module_tenants`:入口模块和租户的可见关系。 +- `leaudit_document_types`:文档类型,通过 `entry_module_id` 归属入口模块。 +- `leaudit_evaluation_point_groups`:规则分组树。 +- `leaudit_rule_group_bindings`:运行时规则绑定唯一事实源。 +- `leaudit_documents`:文档记录,后续需要补 `entry_module_id`。 + +### 3.2 入口模块新增字段 + +给 `leaudit_entry_modules` 增加: + +```sql +ALTER TABLE leaudit_entry_modules +ADD COLUMN IF NOT EXISTS menu_profile VARCHAR(64) NOT NULL DEFAULT 'document_review', +ADD COLUMN IF NOT EXISTS features JSONB NOT NULL DEFAULT '[]'::jsonb; + +CREATE INDEX IF NOT EXISTS idx_leaudit_entry_modules_menu_profile +ON leaudit_entry_modules(menu_profile) +WHERE deleted_at IS NULL; +``` + +字段解释: + +- `menu_profile`:菜单模板字段,比如合同工作台、公文工作台、通用文档评查。 +- `features`:功能清单字段,表示该入口模块启用哪些功能菜单。 + +### 3.3 文档表新增字段 + +给 `leaudit_documents` 增加: + +```sql +ALTER TABLE leaudit_documents +ADD COLUMN IF NOT EXISTS entry_module_id BIGINT NULL REFERENCES leaudit_entry_modules(id); + +CREATE INDEX IF NOT EXISTS idx_leaudit_documents_entry_module_id +ON leaudit_documents(entry_module_id); +``` + +作用: + +- 文档创建后明确知道自己来自哪个入口模块。 +- 文档列表、公文列表、统计、后续质量校验都可以按入口模块过滤。 + +## 四、菜单模板与功能编码 + +### 4.1 菜单模板 + +固定使用这些编码: + +```text +document_review 通用文档评查 +contract 合同工作台 +govdoc 内部公文工作台 +cross_checking 交叉评查工作台 +custom 自定义工作台 +``` + +### 4.2 功能编码 + +固定使用这些编码: + +```text +home 首页/概览 +documents 文档列表 +upload 文件上传 +rules 规则配置 +rule_groups 规则分组 +contract_template_search 合同模板搜索 +contract_template_list 合同模板列表 +govdoc_audits 公文列表 +govdoc_upload 公文上传 +cross_checking 交叉评查 +cross_checking_upload 创建交叉评查任务 +cross_checking_list 交叉评查任务列表 +usage_stats 使用统计 +``` + +### 4.3 默认功能 + +如果老数据没有配置功能清单字段,就按菜单模板字段自动补默认值: + +```json +{ + "document_review": ["home", "documents", "upload", "rules", "rule_groups"], + "contract": ["home", "documents", "upload", "rules", "contract_template_search", "contract_template_list"], + "govdoc": ["home", "govdoc_audits", "govdoc_upload", "rule_groups"], + "cross_checking": ["cross_checking", "cross_checking_upload", "cross_checking_list"], + "custom": ["home", "documents"] +} +``` + +## 五、多租户规则 + +这里必须沿用你当前项目已有模型,不新造租户体系。 + +### 5.1 入口模块可见性 + +入口模块是否对某个租户可见,继续由 `leaudit_entry_module_tenants` 控制。 + +判断规则: + +```text +用户 tenant_code 命中 leaudit_entry_module_tenants.tenant_code +并且 leaudit_entry_module_tenants.is_enabled = true +并且 leaudit_entry_modules.is_enabled = true +并且入口模块没有 deleted_at +``` + +特殊情况: + +- `PUBLIC` 可以作为公共入口模块。 +- 超级管理员或全局管理员可以跨租户查看。 +- 旧的地区字段暂时保留兼容,但不再作为新逻辑主模型。 + +### 5.2 功能菜单是否需要租户级差异 + +第一阶段不做“同一个入口模块不同租户显示不同功能”。 + +第一阶段规则: + +```text +入口模块功能清单对所有可见租户一致 +租户只控制入口模块是否可见 +``` + +如果后续真有需求,例如同一个入口模块云浮显示模板搜索、梅州不显示模板搜索,再扩展: + +```sql +ALTER TABLE leaudit_entry_module_tenants +ADD COLUMN IF NOT EXISTS features_override JSONB NULL, +ADD COLUMN IF NOT EXISTS menu_profile_override VARCHAR(64) NULL; +``` + +最终生效逻辑: + +```text +租户关系表 features_override 有值 -> 用租户覆盖配置 +否则入口模块 features 有值 -> 用入口模块配置 +否则按 menu_profile 默认功能生成 +``` + +第一阶段先不要上这个复杂度。 + +### 5.3 入口模块配置权限 + +入口模块是系统级业务工作台配置,但不要在代码里硬编码“只有某个角色名能配置”。正确口径是:谁被分配了入口模块管理权限,谁才能配置入口模块。 + +也就是说: + +```text +不要写死 role_key = super_admin +不要写死 role_key = provincial_admin +不要写死市区管理员一定不能操作 +``` + +后端只认权限点: + +```text +entry_module:list:read 查看入口模块列表 +entry_module:detail:read 查看入口模块详情 +entry_module:create:write 创建入口模块 +entry_module:update:write 编辑入口模块 +entry_module:delete:delete 删除入口模块 +entry_module:image:write 上传或替换入口模块图标 +``` + +推荐默认分配策略: + +```text +系统超级管理员角色:默认分配入口模块全部管理权限 +省级管理员角色:默认不分配创建/编辑/删除入口模块权限,是否开放由实际授权决定 +市区管理员角色:默认不分配创建/编辑/删除入口模块权限,是否开放由实际授权决定 +``` + +所以最终判断不是“这个人是不是超级管理员”,而是: + +```text +能不能创建入口模块 -> 看有没有 entry_module:create:write +能不能编辑入口模块 -> 看有没有 entry_module:update:write +能不能删除入口模块 -> 看有没有 entry_module:delete:delete +能不能上传图标 -> 看有没有 entry_module:image:write +``` + +三层边界必须分清: + +```text +RBAC 权限点:控制谁能配置入口模块 +入口模块租户关系:控制哪个租户能看到/使用入口模块 +入口模块 features + 页面/API 权限:控制进入入口后能看到和使用哪些功能 +``` + +举例: + +```text +某个市区管理员没有 entry_module:create:write +即使他属于云浮租户,也不能新建入口模块 + +某个市区管理员有 entry_module:create:write +他就可以进入入口模块管理页执行创建动作 +但创建出来的入口能被哪些租户看到,仍然必须写入 leaudit_entry_module_tenants +``` + +## 六、一级分组、二级分组、规则绑定设计 + +这一块是本次重构最关键的业务边界。入口模块只解决“用户从哪个工作台进来”,规则分组解决“这个工作台下有哪些业务类型”,规则绑定解决“这个业务类型运行哪套规则”。 + +### 6.1 最终业务口径 + +固定使用两层分组,不继续发散: + +```text +入口模块 + -> 一级分组:业务大类 + -> 二级分组:具体运行类型 + -> 规则绑定:绑定规则集 +``` + +举例: + +```text +入口模块:合同评查 +一级分组:合同 +二级分组:建设工程合同、买卖合同、租赁合同 +规则绑定:建设工程合同 -> 建设工程合同规则集 +``` + +再举例: + +```text +入口模块:内部公文 +一级分组:内部公文 +二级分组:请示、通知、会议纪要 +规则绑定:请示 -> 请示规则集 +``` + +### 6.2 一级分组职责 + +一级分组只表达业务大类,不直接参与运行时规则命中。 + +数据库仍然复用: + +```text +leaudit_evaluation_point_groups +``` + +一级分组判断: + +```text +pid = 0 +``` + +一级分组字段规则: + +```text +entry_module_id 必填,表示这个一级分组属于哪个入口模块 +document_type_id 为空,不直接绑定具体文档类型 +name 使用业务大类名称,例如 合同、内部公文、行政卷宗 +``` + +也就是说,入口模块页面里的“规则分组”应该先看到这个入口模块下的一级分组,而不是全系统所有分组。 + +### 6.3 二级分组职责 + +二级分组才是实际运行类型,也就是用户上传、列表过滤、评查执行真正要落的 `groupId`。 + +二级分组判断: + +```text +pid != 0 +``` + +二级分组字段规则: + +```text +pid 指向一级分组 id +document_type_id 必填,表示这个二级分组对应哪个具体文档类型 +entry_module_id 可以冗余保存,也可以从一级分组继承,但查询时必须能按入口模块过滤 +``` + +前端显示时,用户理解成: + +```text +一级分组 = 大类 +二级分组 = 具体要评查的文档类型/运行类型 +``` + +后端理解成: + +```text +文档最终必须落到二级分组 group_id +``` + +### 6.4 规则绑定职责 + +规则绑定只允许挂二级分组,不允许挂一级分组。 + +继续使用: + +```text +leaudit_rule_group_bindings +``` + +绑定关系: + +```text +leaudit_rule_group_bindings.group_id = 二级分组 id +leaudit_rule_group_bindings.rule_set_id = 规则集 id +``` + +禁止口径: + +```text +不要把规则集挂在一级分组 +不要再按入口模块名称猜规则集 +不要再绕回旧的文档类型规则绑定表作为主链路 +``` + +运行时唯一主链路: + +```text +document.group_id + -> leaudit_rule_group_bindings.group_id + -> rule_set_id + -> 当前可执行规则版本 +``` + +### 6.5 多租户下规则怎么生效 + +分组树本身不建议第一阶段按租户复制一份。否则云浮、梅州、揭阳每个租户一套树,后面维护会爆炸。 + +第一阶段建议: + +```text +入口模块租户关系:控制哪个租户看得到哪个入口模块 +一级/二级分组:表达入口模块下的业务结构 +规则绑定 tenant_code/scope_type:控制不同租户实际运行哪套规则集 +``` + +也就是说: + +```text +同一个二级分组,可以存在多条规则绑定 +``` + +例如: + +```text +二级分组:建设工程合同 +云浮租户 -> 云浮建设工程合同规则集 +梅州租户 -> 梅州建设工程合同规则集 +省级兜底 -> 通用建设工程合同规则集 +``` + +运行时选择顺序: + +```text +优先当前租户绑定 +没有当前租户绑定,再走省级/公共兜底绑定 +仍然没有,就提示该二级分组未配置有效规则 +``` + +### 6.6 上传、列表、评查的字段落点 + +上传时必须落这些字段: + +```text +entry_module_id:从哪个入口进来 +type_id:具体文档类型 +group_id:二级分组 id +tenant_code:当前租户 +``` + +如果上传时只传了文档类型,没有传二级分组,后端只能在“该文档类型只有一个可用二级分组”时兜底推断。只要有多个二级分组,就必须让用户明确选择,否则规则命中会不稳定。 + +列表过滤顺序: + +```text +先按 tenant_code 做租户边界 +再按 entry_module_id 做入口模块范围 +再按 group_id/type_id 做具体业务过滤 +``` + +评查执行顺序: + +```text +读取文档 group_id +确认 group_id 是二级分组 +按 group_id + tenant_code 找有效规则绑定 +取 rule_set 当前可执行版本 +执行评查 +``` + +### 6.7 后台页面怎么改 + +入口模块管理页: + +```text +只负责入口模块本身、菜单功能、租户可见性 +不在这里直接绑规则集 +``` + +文档类型管理页: + +```text +负责维护具体文档类型属于哪个入口模块 +可以辅助展示它被哪个二级分组使用 +``` + +规则分组页: + +```text +进入某入口模块后,只显示该入口模块下的一级分组 +一级分组下面维护二级分组 +二级分组上配置规则绑定 +``` + +规则绑定页或弹窗: + +```text +只能从二级分组进入 +可以配置当前租户绑定、省级兜底绑定、公共绑定 +保存到 leaudit_rule_group_bindings +``` + +### 6.8 必须加的校验 + +后端保存规则分组时必须校验: + +```text +一级分组 pid = 0 时,必须有 entry_module_id +一级分组不允许绑定 rule_set +二级分组 pid != 0 时,必须有 document_type_id +二级分组所属一级分组必须和当前入口模块一致 +二级分组才允许写 leaudit_rule_group_bindings +上传文档时传入的 group_id 必须是二级分组 +上传文档时 group_id 对应的入口模块必须等于 entry_module_id +``` + +建议补充数据库约束或唯一索引: + +```sql +CREATE UNIQUE INDEX IF NOT EXISTS uq_leaudit_ep_groups_parent_doc_type_active +ON leaudit_evaluation_point_groups(pid, document_type_id) +WHERE deleted_at IS NULL + AND COALESCE(pid, 0) <> 0 + AND document_type_id IS NOT NULL; +``` + +作用是避免同一个一级分组下面重复挂同一个文档类型,导致上传时无法稳定推断二级分组。 + +### 6.9 旧数据兼容策略 + +当前系统里可能还有旧结构: + +```text +一级分组 = 具体文档类型 +二级分组 = 通用 +``` + +这个是过渡结构,不要继续加深。 + +兼容策略: + +```text +短期:后端查询同时兼容旧结构,避免线上功能直接断 +中期:迁移成 一级=业务大类、二级=具体文档类型 +长期:规则绑定只认二级分组,旧结构下线 +``` + +迁移示例: + +```text +旧: +一级:建设工程合同 +二级:通用 +规则绑定:通用 -> 规则集 + +新: +一级:合同 +二级:建设工程合同 +规则绑定:建设工程合同 -> 原规则集 +``` + +这一段迁移可以参考已有脚本: + +```text +scripts/创建sql/migrate_rule_groups_to_business_roots.sql +scripts/创建sql/precheck_rule_group_migration.sql +``` + +## 七、后端改造范围 + +### 7.1 后端请求对象 + +文件: + +```text +fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py +``` + +给 `EntryModuleCreateDTO` 和 `EntryModuleUpdateDTO` 增加: + +```python +menu_profile: str | None = Field(None, description="菜单模板:document_review/contract/govdoc/cross_checking/custom") +features: list[str] | None = Field(None, description="启用功能编码列表") +``` + +### 7.2 后端返回对象 + +文件: + +```text +fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py +fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py +``` + +入口模块管理返回对象增加: + +```python +menu_profile: str = Field("document_review", description="菜单模板") +features: list[str] = Field(default_factory=list, description="启用功能编码列表") +business_scope: EntryModuleBusinessScopeVO = Field(default_factory=EntryModuleBusinessScopeVO, description="业务范围摘要") +``` + +首页入口返回对象增加: + +```python +menuProfile: str = Field("document_review", description="菜单模板") +features: list[str] = Field(default_factory=list, description="启用功能编码列表") +tenantCode: str | None = Field(None, description="当前命中的租户编码") +``` + +### 7.3 入口模块管理服务 + +文件: + +```text +fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py +``` + +要做: + +1. 确保菜单模板字段和功能清单字段存在。 +2. 创建入口模块时保存菜单模板和功能清单。 +3. 更新入口模块时保存菜单模板和功能清单。 +4. 查询列表和详情时返回这两个字段。 +5. 查询列表和详情时返回业务范围摘要 `business_scope`,用于前端展示已绑定业务大类和业务类型数量。 +6. 校验菜单模板和功能清单只能使用允许的编码。 +7. 继续沿用现有入口模块权限点做接口控制,不要额外硬编码角色名。 +8. 如果当前用户没有对应权限点,后端直接返回 403,不能只靠前端隐藏按钮。 + +允许值: + +```python +_ALLOWED_MENU_PROFILES = {"document_review", "contract", "govdoc", "cross_checking", "custom"} +_ALLOWED_FEATURES = { + "home", + "documents", + "upload", + "rules", + "rule_groups", + "contract_template_search", + "contract_template_list", + "govdoc_audits", + "govdoc_upload", + "cross_checking", + "cross_checking_upload", + "cross_checking_list", + "usage_stats", +} +``` + +### 7.4 首页入口服务 + +文件: + +```text +fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py +``` + +要做: + +1. 保持现有 `leaudit_entry_module_tenants` 过滤逻辑不变。 +2. 查询入口模块时带出菜单模板和功能清单。 +3. 返回给首页,前端点击入口时存起来。 +4. 返回当前命中的租户编码,方便前端继续传递上下文。 + +### 7.5 文档服务 + +文件: + +```text +fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py +fastapi_modules/fastapi_leaudit/controllers/documentController.py +``` + +要做: + +1. 上传接口接收 `entryModuleId`。 +2. 创建文档时写入 `entry_module_id`。 +3. 如果前端没传,则按: + +```text +二级分组 entry_module_id -> 一级分组 entry_module_id -> 文档类型 entry_module_id +``` + +兜底解析。 + +4. 文档列表过滤时使用: + +```sql +COALESCE(d.entry_module_id, eg.entry_module_id, eg_parent.entry_module_id, dt.entry_module_id) = :entry_module_id +``` + +### 7.6 公文服务 + +文件: + +```text +fastapi_modules/fastapi_leaudit/controllers/govdocController.py +fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py +``` + +要做: + +1. `/api/govdoc/documents` 增加 `entry_module_id` 查询参数。 +2. `GovdocServiceImpl.ListDocuments` 增加 `EntryModuleId` 参数。 +3. 查询时按: + +```sql +COALESCE(d.entry_module_id, dt.entry_module_id) = :entry_module_id +``` + +过滤。 + +4. 继续保留现有: + +```sql +COALESCE(d.engine_type, 'leaudit') = 'govdoc' +``` + +也就是说: + +```text +公文列表 = 文档引擎类型是公文 + 当前入口模块范围 +``` + +### 7.7 规则分组服务 + +文件: + +```text +fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py +fastapi_modules/fastapi_leaudit/services/impl/ruleConfigServiceImpl.py +``` + +要做: + +1. 规则组列表按 `entry_module_id` 过滤。 +2. 过滤表达式统一用: + +```sql +COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) +``` + +3. 入口模块只决定“用户看到哪些规则组”,不参与运行时选规则。 +4. 运行时选规则继续保持: + +```text +document.group_id -> leaudit_rule_group_bindings -> rule_set/rule_version +``` + +## 八、前端改造范围 + +### 8.0 前端 UI 风格约束 + +本次前端改造必须和当前系统 UI 设计、样式、配色保持统一,不允许为了新功能另起一套视觉风格。 + +统一要求: + +```text +继续使用当前系统已有的 Card、Button、Table、FilterPanel、FilterSelect、SearchFilter、Pagination、Modal 等组件 +继续使用当前页面已有的 CSS 变量和主题色 +继续沿用现有后台管理页的布局、间距、圆角、阴影、表格操作列样式 +继续沿用现有 toast、loading、empty state、403 提示样式 +新增表单项要和当前入口模块编辑页的表单布局一致 +新增功能勾选区要像现有权限/配置类页面一样清晰,不做花哨卡片风格 +``` + +禁止: + +```text +不要新增一套独立主题色 +不要引入新的 UI 框架 +不要写和当前后台风格不一致的大面积渐变、特殊字体、复杂动效 +不要把入口模块管理页改成和系统其他管理页完全不同的视觉 +不要为了功能勾选单独设计一套复杂组件 +``` + +具体页面要求: + +```text +入口模块列表页:沿用当前表格、筛选、操作按钮风格 +入口模块编辑页:沿用当前表单分组风格,只增加菜单模板和功能勾选 +侧边栏:沿用当前菜单高亮、图标、折叠、权限过滤表现 +规则分组页:沿用当前树/列表/弹窗样式,不重做视觉 +上传页:只补入口模块上下文和二级分组选择,不重做上传区视觉 +公文列表页:只改标题和过滤参数,不重做列表视觉 +``` + +如果必须新增样式,优先放在现有对应页面样式文件里,并复用当前 CSS 变量,例如: + +```text +var(--color-primary-text) +var(--color-primary-text-muted) +var(--color-border) +var(--color-surface) +``` + +### 8.1 入口模块前端接口类型 + +文件: + +```text +legal-platform-frontend/lib/api/legacy/entry-modules/entry-modules.ts +legal-platform-frontend/lib/api/legacy/entry-modules/request-body.ts +``` + +增加类型: + +```ts +export type EntryModuleMenuProfile = "document_review" | "contract" | "govdoc" | "cross_checking" | "custom"; +export type EntryModuleFeature = + | "home" + | "documents" + | "upload" + | "rules" + | "rule_groups" + | "contract_template_search" + | "contract_template_list" + | "govdoc_audits" + | "govdoc_upload" + | "cross_checking" + | "cross_checking_upload" + | "cross_checking_list" + | "usage_stats"; +``` + +入口模块类型增加: + +```ts +menu_profile?: EntryModuleMenuProfile | string; +features?: EntryModuleFeature[] | string[]; +business_scope?: { + category_count: number; + business_type_count: number; + categories: string[]; +} | null; +``` + +请求体增加: + +```ts +menu_profile?: string | null; +features?: string[]; +``` + +### 8.2 入口模块编辑页 + +文件: + +```text +legal-platform-frontend/app/(audit)/entry-modules/new/EntryModuleNewClient.tsx +``` + +页面增加两个配置区: + +1. 菜单模板选择: + +```text +通用文档评查 +合同工作台 +内部公文工作台 +自定义工作台 +``` + +2. 功能勾选: + +```text +文档列表 +文件上传 +规则配置 +规则分组 +模板搜索 +模板列表 +公文列表 +公文上传 +交叉评查 +创建交叉评查任务 +交叉评查任务列表 +使用统计 +``` + +用户选择菜单模板后,自动带出默认功能,用户可以再调整。 + +权限显示规则: + +```text +没有 entry_module:create:write:隐藏新建入口模块按钮 +没有 entry_module:update:write:隐藏或禁用保存修改按钮 +没有 entry_module:delete:delete:隐藏删除按钮 +没有 entry_module:image:write:隐藏或禁用上传图标能力 +``` + +注意:前端隐藏只是体验优化,最终以后端权限点校验为准。 + +### 8.3 首页点击入口 + +文件: + +```text +legal-platform-frontend/app/page.tsx +``` + +点击入口模块时,除了原来的 `selectedModuleId/selectedModuleName`,还要保存: + +```ts +{ + id, + name, + targetPath, + menuProfile, + features, + tenantCode, + documentTypeIds, + iconPath +} +``` + +建议统一封装到新文件: + +```text +legal-platform-frontend/lib/auth/entry-module-context.ts +``` + +同时 URL 必须带: + +```text +entryModuleId=xxx +documentTypeIds=1,2,3 +``` + +不能只依赖 sessionStorage,否则刷新和复制链接会丢上下文。 + +### 8.4 侧边栏菜单 + +文件: + +```text +legal-platform-frontend/components/layout/Sidebar.tsx +legal-platform-frontend/lib/auth/entry-module-menu.ts +``` + +新增 `entry-module-menu.ts`,把功能编码转成菜单: + +```ts +documents -> 文档列表 /documents +upload -> 文件上传 /files/upload +rules -> 规则配置 /rules-test/list +rule_groups -> 规则分组 /rule-groups +contract_template_search -> 模板搜索 /contract-template/search +contract_template_list -> 模板列表 /contract-template/list +govdoc_audits -> 公文列表 /govdoc/audits +govdoc_upload -> 公文上传 /govdoc/upload +cross_checking -> 交叉评查 /cross-checking +cross_checking_upload -> 创建任务 /cross-checking/upload +cross_checking_list -> 评查任务列表 /cross-checking/list +``` + +侧边栏必须删除这些判断: + +```ts +selectedModuleName.includes("合同") +selectedModuleName.includes("公文") +shouldUseGovdocAuditMenu(effectiveSelectedModuleName) +``` + +改成: + +```text +读取当前入口模块功能清单 +功能清单决定显示哪些菜单 +角色权限系统再过滤用户没权限的菜单 +``` + +重点: + +```text +功能清单不能绕过角色权限系统 +``` + +如果入口模块启用了“模板列表”,但用户角色没有模板列表页面权限,仍然不能显示或访问。 + +入口模块管理菜单本身也要按权限点显示: + +```text +有 entry_module:list:read 才显示入口模块管理菜单 +没有 entry_module:list:read 即使知道路径也不能正常加载数据 +``` + +### 8.5 公文列表页面 + +文件: + +```text +legal-platform-frontend/components/govdoc-audit/audits.tsx +legal-platform-frontend/lib/api/govdoc-audit/api.ts +``` + +要做: + +1. 从 URL 或入口模块上下文读取 `entryModuleId`。 +2. 调用 `api.listAudits()` 时传入 `entryModuleId`。 +3. `api.listAudits()` 转成后端参数: + +```text +entry_module_id=xxx +``` + +4. 页面标题/侧边栏显示当前入口模块名,不再写死“内部公文”。 + +### 8.6 上传页面 + +文件: + +```text +legal-platform-frontend/app/(audit)/files/upload/FilesUploadClient.tsx +``` + +要做: + +1. 上传时读取当前入口模块上下文。 +2. 上传表单数据增加: + +```text +entryModuleId +``` + +3. 继续保留: + +```text +typeId +groupId +tenantCode +``` + +上传后的文档必须具备完整归属: + +```text +entry_module_id + type_id + group_id + tenant_code +``` + +## 九、SQL 迁移脚本 + +建议新增: + +```text +scripts/创建sql/entry_module_menu_profile_migration.sql +``` + +内容: + +```sql +ALTER TABLE leaudit_entry_modules +ADD COLUMN IF NOT EXISTS menu_profile VARCHAR(64) NOT NULL DEFAULT 'document_review', +ADD COLUMN IF NOT EXISTS features JSONB NOT NULL DEFAULT '[]'::jsonb; + +ALTER TABLE leaudit_documents +ADD COLUMN IF NOT EXISTS entry_module_id BIGINT NULL REFERENCES leaudit_entry_modules(id); + +CREATE INDEX IF NOT EXISTS idx_leaudit_entry_modules_menu_profile +ON leaudit_entry_modules(menu_profile) +WHERE deleted_at IS NULL; + +CREATE INDEX IF NOT EXISTS idx_leaudit_documents_entry_module_id +ON leaudit_documents(entry_module_id); + +CREATE UNIQUE INDEX IF NOT EXISTS uq_leaudit_ep_groups_parent_doc_type_active +ON leaudit_evaluation_point_groups(pid, document_type_id) +WHERE deleted_at IS NULL + AND COALESCE(pid, 0) <> 0 + AND document_type_id IS NOT NULL; +``` + +旧数据回填: + +```sql +UPDATE leaudit_entry_modules +SET + menu_profile = CASE + WHEN path IN ('/govdoc/audits', '/govdoc', '/govdoc-audit') THEN 'govdoc' + WHEN path IN ('/contract-template', '/contract-template/list', '/contract-template/search') THEN 'contract' + ELSE COALESCE(NULLIF(menu_profile, ''), 'document_review') + END, + features = CASE + WHEN path IN ('/govdoc/audits', '/govdoc', '/govdoc-audit') + THEN '["home","govdoc_audits","govdoc_upload","rule_groups"]'::jsonb + WHEN path IN ('/contract-template', '/contract-template/list', '/contract-template/search') + THEN '["home","documents","upload","rules","contract_template_search","contract_template_list"]'::jsonb + WHEN features = '[]'::jsonb + THEN '["home","documents","upload","rules","rule_groups"]'::jsonb + ELSE features + END +WHERE deleted_at IS NULL; +``` + +文档归属回填: + +```sql +UPDATE leaudit_documents d +SET entry_module_id = COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) +FROM leaudit_document_types dt +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 +WHERE d.type_id = dt.id + AND d.entry_module_id IS NULL; +``` + +验证脚本: + +```sql +SELECT id, name, path, menu_profile, features +FROM leaudit_entry_modules +WHERE deleted_at IS NULL +ORDER BY sort_order, id; + +SELECT COUNT(*) AS documents_without_entry_module +FROM leaudit_documents +WHERE deleted_at IS NULL + AND entry_module_id IS NULL; +``` + +## 十、实施顺序 + +### 第一阶段:先修用户能看到的问题 + +目标: + +```text +入口模块名字不含合同/公文,也能按配置显示正确菜单 +``` + +任务: + +1. 后端入口模块请求对象和返回对象增加菜单模板、功能清单。 +2. 入口模块管理页支持菜单模板和功能勾选。 +3. 首页返回入口模块时带菜单模板、功能清单。 +4. 首页点击入口时保存完整上下文。 +5. 侧边栏改成按功能清单生成菜单。 +6. 删除侧边栏按名称包含“合同/公文”的判断。 + +### 第二阶段:列表和上传真正按入口过滤 + +目标: + +```text +进入哪个入口模块,就只看这个入口模块下的文档和公文 +``` + +任务: + +1. 文档上传保存 `entry_module_id`。 +2. 普通文档列表按 `entry_module_id` 过滤。 +3. 公文列表按 `entry_module_id` 过滤。 +4. 公文列表前端传 `entryModuleId`。 +5. 页面刷新后仍能从 URL 恢复入口上下文。 + +### 第三阶段:规则分组范围统一 + +目标: + +```text +规则分组页面只显示当前入口模块相关规则组 +``` + +任务: + +1. 规则分组列表支持 `entry_module_id`。 +2. 前端规则分组页面从 URL/session 读取当前入口。 +3. 规则组创建时继承当前入口模块。 +4. 二级分组绑定具体文档类型。 +5. 规则绑定仍然只挂二级分组。 +6. 上传和评查接口校验 `group_id` 必须是二级分组。 +7. 规则绑定保存接口拒绝一级分组。 + +### 第四阶段:旧逻辑下线 + +目标: + +```text +不再靠名字和路径猜业务类型 +``` + +任务: + +1. 删除 `includes("合同")` 决定合同菜单的逻辑。 +2. 删除 `includes("公文")` 决定公文菜单的逻辑。 +3. 删除 `/govdoc` 强制显示“内部公文”的逻辑。 +4. 保留路径字段只作为跳转地址。 +5. 旧地区字段保留兼容,但新写入只走租户关系。 + +## 十一、验收标准 + +### 11.1 合同入口验收 + +配置: + +```text +入口模块名称:入口模块-测试 +menu_profile:contract +features:contract_template_search, contract_template_list +租户:云浮 +``` + +预期: + +```text +云浮用户首页能看到该入口 +点击后左侧显示模板搜索、模板列表 +入口名字不包含“合同”也正常显示 +其他未绑定租户看不到该入口 +没有角色权限的用户仍然不能访问模板页面 +``` + +### 11.2 公文入口验收 + +配置: + +```text +入口模块名称:入口模块-测试 +route_path:/govdoc/audits +menu_profile:govdoc +features:govdoc_audits +租户:梅州 +``` + +预期: + +```text +梅州用户首页能看到该入口 +点击进入 /govdoc/audits +页面显示入口模块-测试,而不是固定显示内部公文 +公文列表请求带 entry_module_id +列表只显示该入口模块范围内的公文 +``` + +### 11.3 文档列表验收 + +配置: + +```text +入口 A 绑定文档类型 A +入口 B 绑定文档类型 B +同一个租户下分别上传文档 +``` + +预期: + +```text +从入口 A 进入只看到 A 的文档 +从入口 B 进入只看到 B 的文档 +刷新页面后过滤条件不丢 +``` + +### 11.3.1 交叉评查入口验收 + +配置: + +```text +入口模块名称:入口模块-测试交叉评查 +route_path:/cross-checking +menu_profile:cross_checking +features:cross_checking, cross_checking_upload, cross_checking_list +租户:目标租户或 PUBLIC +``` + +预期: + +```text +目标租户首页能看到该入口 +点击进入 /cross-checking +侧边栏显示交叉评查、创建任务、评查任务列表 +没有交叉评查路由权限的用户即使入口模块启用交叉评查功能,也不能看到或访问交叉评查菜单 +``` + +### 11.4 多租户验收 + +配置: + +```text +入口模块 X 只绑定云浮 +入口模块 Y 只绑定梅州 +入口模块 Z 绑定 PUBLIC +``` + +预期: + +```text +云浮用户看到 X 和 Z +梅州用户看到 Y 和 Z +普通用户看不到其他租户入口 +超级管理员可以跨租户管理 +角色权限仍然控制页面和接口能不能访问 +``` + +### 11.5 规则分组和规则绑定验收 + +配置: + +```text +入口模块:合同评查 +一级分组:合同 +二级分组:建设工程合同 +规则绑定:建设工程合同 -> 建设工程合同规则集 +租户:云浮 +``` + +预期: + +```text +从合同评查入口进入,只看到合同一级分组 +建设工程合同显示在合同一级分组下面 +规则绑定只能在建设工程合同这个二级分组上配置 +一级分组合同不能直接绑定规则集 +上传建设工程合同后,文档 group_id 等于建设工程合同二级分组 id +评查时按 group_id + tenant_code 命中云浮对应规则集 +``` + +### 11.6 入口模块配置权限验收 + +配置: + +```text +角色 A 分配 entry_module:list:read +角色 A 不分配 entry_module:create:write / entry_module:update:write / entry_module:delete:delete + +角色 B 分配 entry_module:list:read / entry_module:create:write / entry_module:update:write +角色 B 不分配 entry_module:delete:delete +``` + +预期: + +```text +角色 A 可以查看入口模块列表 +角色 A 看不到新建、编辑保存、删除入口模块能力 +角色 A 直接调用创建/编辑/删除接口返回 403 + +角色 B 可以查看入口模块列表 +角色 B 可以创建和编辑入口模块 +角色 B 不能删除入口模块 +角色 B 直接调用删除接口返回 403 +``` + +关键验收点: + +```text +系统不通过 role_key 硬编码判断谁能配置入口模块 +入口模块配置权限完全由 RBAC 权限点分配决定 +入口模块租户关系只控制可见和使用,不控制谁能配置 +``` + +## 十二、非目标 + +这次重构不做: + +- 不删除角色权限系统。 +- 不删除 `leaudit_rule_type_bindings`。 +- 不改变“文档二级分组 -> 规则绑定 -> 规则集版本”的运行时主链路。 +- 不把入口模块变成权限系统。 +- 不第一阶段支持“同一入口不同租户不同菜单”。 +- 不硬编码某个角色名才能配置入口模块,入口模块管理能力由权限点分配决定。 + +运行时规则仍然保持: + +```text +document.group_id -> leaudit_rule_group_bindings -> rule_set/rule_version +``` + +入口模块只负责: + +```text +用户从哪里进来 +左侧显示哪些菜单 +文档/规则/上传属于哪个业务范围 +``` + +## 十三、风险控制 + +1. `menu_profile/features` 设置默认值,保证老入口模块不崩。 +2. 旧地区字段暂时保留兼容,避免历史数据立即失效。 +3. 功能清单生成菜单后还要经过角色权限过滤,不能绕过权限。 +4. 浏览器地址参数必须带 `entryModuleId`,不能只靠浏览器临时缓存。 +5. 文档上传必须保存 `entry_module_id/type_id/group_id/tenant_code`,后续列表和统计才稳定。 +6. 第一阶段先解决菜单和入口体验,规则运行链路不乱动。 +7. 一级分组只做业务大类,二级分组才做运行类型,规则绑定只能挂二级分组。 +8. 入口模块管理不能靠前端隐藏按钮保证安全,后端必须按权限点返回 403。 + +## 十四、Superpowers 执行任务清单 + +本节是给后续开发直接执行的任务清单。执行时必须从上到下推进,每完成一个小任务就验证一次,不要一次性大改完再排错。 + +### 14.1 执行原则 + +- [x] 先做数据库和后端返回字段,再做前端展示。 +- [x] 先解决入口模块菜单显示错误,再处理列表和上传过滤。 +- [x] 不改运行时评查主链路,只补入口模块、分组、文档归属。 +- [x] 不硬编码角色名判断入口模块管理权限,只使用 RBAC 权限点。 +- [x] 每一步都保留旧数据兼容,避免老入口模块、老文档、旧规则分组直接失效。 + +### 14.2 数据库任务 + +- [x] 新增迁移脚本 `scripts/创建sql/entry_module_menu_profile_migration.sql`。 +- [x] 给 `leaudit_entry_modules` 增加 `menu_profile` 字段。 +- [x] 给 `leaudit_entry_modules` 增加 `features` 字段。 +- [x] 给 `leaudit_documents` 增加 `entry_module_id` 字段。 +- [x] 给 `leaudit_documents.entry_module_id` 增加索引。 +- [x] 给 `leaudit_entry_modules.menu_profile` 增加索引。 +- [x] 给 `leaudit_evaluation_point_groups(pid, document_type_id)` 增加二级分组唯一索引。 +- [x] 回填老入口模块的菜单模板和功能清单。 +- [x] 尝试按二级分组、一级分组、文档类型回填历史文档的 `entry_module_id`。 +- [x] 写验证 SQL,检查入口模块字段、文档归属、重复二级分组。 + +### 14.3 后端入口模块任务 + +- [x] 修改 `fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py`,创建和更新请求增加 `menu_profile/features`。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py`,入口模块管理返回增加 `menu_profile/features`。 +- [x] 修改 `entryModuleAdminVo.py` 和 `entryModuleAdminServiceImpl.py`,入口模块列表和详情返回 `business_scope` 业务范围摘要。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py`,首页入口返回增加 `menuProfile/features/tenantCode`。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py`,创建入口模块时保存菜单模板和功能清单。 +- [x] 修改 `entryModuleAdminServiceImpl.py`,更新入口模块时保存菜单模板和功能清单。 +- [x] 修改 `entryModuleAdminServiceImpl.py`,列表和详情查询返回菜单模板和功能清单。 +- [x] 修改 `entryModuleAdminServiceImpl.py`,列表和详情查询返回已绑定业务大类数量、业务类型数量和大类名称列表。 +- [x] 在 `entryModuleAdminServiceImpl.py` 增加菜单模板、功能编码白名单校验。 +- [x] 保留 `entryModuleController.py` 现有权限点校验,不新增角色名硬编码。 +- [x] 确认没有权限点时,创建、编辑、删除、上传图标接口都返回 403。 + +### 14.4 后端首页和入口上下文任务 + +- [x] 修改 `fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py`,首页入口查询带出 `menu_profile/features`。 +- [x] 首页入口仍按 `leaudit_entry_module_tenants` 过滤当前租户可见入口。 +- [x] 首页入口返回当前命中的租户编码。 +- [x] 首页入口返回文档类型范围,方便前端拼接上下文。 +- [x] 保持 `PUBLIC` 入口模块兼容。 +- [x] 保持老地区字段兼容,但新链路以租户关系为准。 + +### 14.5 后端文档和公文任务 + +- [x] 修改文档上传接口,接收 `entryModuleId`。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py`,创建文档时写入 `entry_module_id`。 +- [x] 上传时校验 `group_id` 是二级分组。 +- [x] 上传时校验 `group_id` 所属入口模块与 `entryModuleId` 一致。 +- [x] 当前端没传 `group_id` 时,只允许在唯一可用二级分组场景下兜底推断。 +- [x] 普通文档列表支持按 `entry_module_id` 过滤。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/controllers/govdocController.py`,公文列表接收 `entry_module_id`。 +- [x] 修改 `fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py`,公文列表按 `entry_module_id` 过滤。 +- [x] 公文列表继续保留公文引擎类型过滤。 + +### 14.6 后端规则分组和规则绑定任务 + +- [x] 修改 `fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py`,规则分组列表支持按入口模块过滤。 +- [ ] 一级分组创建时必须有 `entry_module_id`。 +- [x] 一级分组不允许绑定规则集。 +- [x] 二级分组创建时必须有 `document_type_id`。 +- [x] 二级分组必须挂在当前入口模块下的一级分组下面。 +- [x] 规则绑定保存接口只允许传二级分组 `group_id`。 +- [x] 规则绑定保存接口拒绝一级分组。 +- [x] 规则绑定仍保存到 `leaudit_rule_group_bindings`。 +- [x] 评查运行时继续按 `document.group_id -> leaudit_rule_group_bindings -> rule_set` 命中规则。 +- [x] 不把 `leaudit_rule_type_bindings` 重新作为新主链路。 + +### 14.7 前端入口模块管理任务 + +- [x] 所有新增 UI 必须沿用当前系统组件、CSS 变量、表格、表单、弹窗、按钮风格,不另起视觉体系。 +- [x] 修改 `legal-platform-frontend/lib/api/legacy/entry-modules/entry-modules.ts`,增加菜单模板和功能清单类型。 +- [x] 修改 `legal-platform-frontend/lib/api/legacy/entry-modules/entry-modules.ts`,入口模块类型增加 `business_scope` 摘要字段。 +- [x] 修改 `legal-platform-frontend/lib/api/legacy/entry-modules/request-body.ts`,请求体支持菜单模板和功能清单。 +- [x] 修改 `legal-platform-frontend/app/(audit)/entry-modules/EntryModulesClient.tsx`,列表展示菜单模板和功能摘要。 +- [x] 修改 `EntryModulesClient.tsx`,业务范围列按 `business_scope` 展示真实大类和业务类型数量,不再写死“待配置”。 +- [x] 修改 `legal-platform-frontend/app/(audit)/entry-modules/new/EntryModuleNewClient.tsx`,增加菜单模板选择。 +- [x] 修改 `EntryModuleNewClient.tsx`,增加功能勾选区域。 +- [x] 选择菜单模板时自动带出默认功能。 +- [x] 新建按钮按 `entry_module:create:write` 显示。 +- [x] 保存按钮按 `entry_module:update:write` 显示或禁用。 +- [x] 删除按钮按 `entry_module:delete:delete` 显示。 +- [x] 图标上传按 `entry_module:image:write` 显示或禁用。 +- [x] 前端只做体验控制,后端权限点校验必须保留。 + +### 14.8 前端首页和侧边栏任务 + +- [x] 修改 `legal-platform-frontend/app/page.tsx`,点击入口模块时保存完整入口上下文。 +- [x] 新增 `legal-platform-frontend/lib/auth/entry-module-context.ts`,统一读写入口模块上下文。 +- [x] 入口跳转 URL 带 `entryModuleId`。 +- [x] 入口跳转 URL 带 `documentTypeIds`。 +- [x] 修改 `legal-platform-frontend/lib/auth/entry-module-menu.ts`,把功能编码转换为菜单项。 +- [x] 入口模块支持 `cross_checking` 菜单模板和交叉评查功能编码。 +- [x] 修改 `legal-platform-frontend/components/layout/Sidebar.tsx`,侧边栏按入口模块功能清单生成菜单。 +- [x] 删除 `selectedModuleName.includes("合同")`。 +- [x] 删除 `selectedModuleName.includes("公文")`。 +- [x] 删除按 `/govdoc` 路径强行判断公文菜单的逻辑。 +- [x] 侧边栏生成菜单后继续经过用户页面权限过滤。 +- [x] 有 `entry_module:list:read` 才显示入口模块管理菜单。 + +### 14.9 前端公文、上传、规则分组任务 + +- [x] 公文、上传、规则分组页面只补业务上下文和过滤逻辑,不重做页面视觉。 +- [x] 修改 `legal-platform-frontend/components/govdoc-audit/audits.tsx`,从 URL 或入口上下文读取 `entryModuleId`。 +- [x] 修改 `legal-platform-frontend/lib/api/govdoc-audit/api.ts`,请求参数带 `entry_module_id`。 +- [x] 公文页面标题使用当前入口模块名称,不再写死“内部公文”。 +- [x] 修改 `legal-platform-frontend/app/(audit)/files/upload/FilesUploadClient.tsx`,上传表单带 `entryModuleId`。 +- [x] 上传页选择二级分组后传 `groupId`。 +- [x] 上传页在存在多个二级分组时必须让用户明确选择。 +- [x] 修改 `legal-platform-frontend/app/(audit)/rule-groups/RuleGroupsClient.tsx`,规则分组页读取当前入口模块。 +- [x] 规则分组页只展示当前入口模块下的一级分组。 +- [x] 规则绑定入口只出现在二级分组上。 + +### 14.10 测试和验收任务 + +- [x] 验证入口模块名称不包含“合同”,但配置合同功能后侧边栏仍显示模板搜索和模板列表。 +- [x] 验证入口模块名称不包含“公文”,但配置公文功能后仍进入公文列表。 +- [x] 验证没有模板页面权限时,即使入口模块启用模板功能,侧边栏也不显示模板菜单。 +- [x] 验证云浮租户只能看到分配给云浮或 `PUBLIC` 的入口模块。 +- [x] 验证梅州租户只能看到分配给梅州或 `PUBLIC` 的入口模块。 +- [x] 验证没有 `entry_module:create:write` 的用户不能创建入口模块。 +- [x] 验证没有 `entry_module:update:write` 的用户不能编辑入口模块。 +- [x] 验证没有 `entry_module:delete:delete` 的用户不能删除入口模块。 +- [x] 验证普通文档列表按入口模块隔离。 +- [x] 验证公文列表按入口模块隔离。 +- [x] 验证上传文档写入 `entry_module_id/type_id/group_id/tenant_code`。 +- [x] 验证规则绑定不能挂一级分组。 +- [x] 验证规则绑定能挂二级分组。 +- [x] 验证入口模块列表业务范围列展示真实绑定摘要,不再全部显示“待配置”。 +- [x] 验证评查按文档二级分组命中正确规则集。 + +### 14.10.1 执行记录 2026-05-23 + +- [x] 使用 Playwright 真实账号 `000/admin06111` 登录验证首页入口和侧边栏。 +- [x] 验证点击 `合同评查` 后进入 `/documents/list?entryModuleId=1&documentTypeIds=...`。 +- [x] 验证侧边栏顺序为:首页、文件上传、文档列表、规则管理。 +- [x] 验证文档列表菜单不重复。 +- [x] 验证上传文档按钮可见。 +- [x] 使用 Playwright 跑优先项 `2/3/4/5`:`node /tmp/leaudit-playwright-priority-2-5-v3.js`,结果 `25 pass / 0 fail`。 +- [x] 修复二级分组绑定规则集 500:`evaluationPointGroupServiceImpl._get_binding_row` SQL 中 `{access_filter}` 未注入。 +- [x] 回归验证:二级分组绑定规则集返回 200。 +- [x] 回归验证:`pytest -q tests/test_rule_group_binding_scope.py` 结果 `4 passed`。 +- [x] 回归验证:`legal-platform-frontend` 下 `npx tsc --noEmit --pretty false` 通过。 +- [x] 回归验证:目标 eslint 结果 `0 error / 6 warnings`,warning 为既有 ``、未使用变量类提示。 +- [x] 使用 `./leaudit.sh status` 确认后端、前端、Worker、Beat 均运行。 +- [x] 修复公文入口侧边栏仍使用旧“系统概览/文件管理”菜单的问题,统一为入口模块菜单:首页、公文列表、公文上传、规则分组。 +- [x] 修复公文入口侧边栏混入普通“文件上传”的问题,避免和“公文上传”重复或语义冲突。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 跑页面入口 smoke:`node /tmp/leaudit-playwright-page-entry-suite.js`,结果 `31 pass / 0 fail`。 +- [x] 页面入口 smoke 覆盖:合同入口名称不含“合同”仍显示模板搜索/模板列表;公文入口名称不含“公文”仍进入 `/govdoc/audits`;自定义入口只显示首页/文件上传/文档列表;三类入口刷新后不丢上下文。 +- [x] 使用 Playwright 跑优先项 `2/3/4/5`:`node /tmp/leaudit-playwright-priority-2-5-v3.js`,结果 `25 pass / 0 fail`。 +- [x] 优先项覆盖:上传写入 `entryModuleId/typeId/groupId/tenantCode`、入口 A/B 文档列表隔离、规则分组按入口过滤、一级分组拒绝绑定、二级分组可绑定、无入口管理权限接口返回 403。 +- [x] 补充交叉评查入口模块配置能力:入口模块路由下拉支持 `/cross-checking`,菜单模板支持 `cross_checking`,功能清单支持 `cross_checking/cross_checking_upload/cross_checking_list`。 +- [x] 修复首页交叉评查入口仍走旧“写死交叉评查卡片”的问题,改为按真实入口模块渲染,入口名称、入口 ID、功能清单全部来自 `leaudit_entry_modules`。 +- [x] 修复 `/cross-checking` 入口点击不带入口上下文的问题,跳转统一进入 `/cross-checking/list?entryModuleId=...`。 +- [x] 修复交叉评查入口侧边栏混入普通“文件上传”的问题,只显示 `创建任务/评查任务列表` 等交叉评查功能菜单。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 验证交叉评查入口模块:`node /tmp/leaudit-playwright-cross-entry.js`,结果 `8 pass / 0 fail`。 +- [x] 新增数据库只读巡检脚本:`scripts/创建sql/verify_entry_module_menu_profile.sql`,覆盖字段、索引、非法菜单配置、文档入口归属、重复二级分组、未绑定入口模块一级分组。 +- [x] 补充公文列表标题逻辑:有入口模块上下文时显示当前入口模块名称,例如 `入口模块-测试文档列表`;无上下文时才兜底 `内部公文文档列表`。 +- [x] 补充入口模块管理菜单权限过滤:`/entry-modules` 设置子菜单必须带 `entry_module:list:read` 才显示。 +- [x] 回归验证:`node --test --experimental-strip-types tests/govdoc-audit/govdoc-entry-title.test.mts` 结果 `2 pass / 0 fail`。 +- [x] 回归验证:`node --test --experimental-strip-types tests/govdoc-audit/settings-menu-permission.test.mts` 结果 `1 pass / 0 fail`。 +- [x] 修复 `Sidebar` 中无入口上下文时按 `/govdoc` 路径强行套公文菜单的问题;公文菜单只由入口模块 `menuProfile/features` 决定。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 跑剩余项验收:`node test-results/leaudit-playwright-entry-module-remaining-acceptance.js`,结果 `11 pass / 0 fail`。 +- [x] 剩余项验收覆盖:名字不含“公文”的 govdoc 入口可进入;公文列表标题使用当前入口名称;侧栏只显示 `公文列表/公文上传/规则分组`;无 `entry_module:image:write` 的用户上传入口模块图标返回 403。 + +### 14.10.2 下一步验收和开发安排 + +- [x] Playwright 页面级验收入口模块管理页:新建入口、编辑入口、功能勾选保存、功能回显、租户回显。 +- [x] Playwright 页面级验收上传页:文件上传菜单排第二,真实表单选择文档类型和二级分组后提交。 +- [x] Playwright 页面级验收规则分组页:入口 A/B 切换后页面树隔离,一级分组不出现绑定入口,二级分组绑定弹窗可用。 +- [x] Playwright 页面级验收公文入口:入口名称不含“公文”但配置 `govdoc_audits/govdoc_upload` 后,公文列表和上传可进入。 +- [x] Playwright 页面级验收公文详情页:确认不出现平台 Sidebar + 公文工作区 Sidebar 双侧栏。 +- [x] 多租户真实账号验收:云浮、揭阳、梅州分别只看到已分配或 `PUBLIC` 入口模块。 +- [x] 多租户权限验收:没有入口模块管理权限的租户用户不能在 UI 和接口层创建、编辑、删除入口模块。 +- [x] 评查命中验收:上传带二级分组的文档后,启动评查,确认命中该二级分组绑定规则集。 + +### 14.10.3 当前最新状态 2026-05-23 + +当前入口模块主链路已经完成: + +- [x] 入口模块不再靠名称包含“合同/公文”决定菜单。 +- [x] 入口模块支持 `document_review/contract/govdoc/cross_checking/custom` 菜单模板。 +- [x] 入口模块支持 `features` 控制首页、上传、文档列表、规则、规则分组、模板、公文、交叉评查菜单。 +- [x] 首页点击入口后会保存完整入口上下文,并在 URL 带 `entryModuleId/documentTypeIds`。 +- [x] 侧边栏菜单由入口模块 `menuProfile/features` 生成,再经过用户页面权限过滤。 +- [x] 普通文档上传和列表已经接入 `entry_module_id/type_id/group_id/tenant_code`。 +- [x] 公文列表接口已经支持 `entry_module_id`,页面标题已经改为当前入口模块名称。 +- [x] 规则分组列表已经支持入口模块过滤,规则绑定只允许挂二级分组。 +- [x] 入口模块管理权限不硬编码角色名,创建、编辑、删除、上传图标走 RBAC 权限点。 +- [x] 数据库迁移脚本和只读验证 SQL 已补齐。 + +当前仍然需要验收或收口: + +- [x] 模板页面权限过滤:入口模块启用模板功能,但用户没有模板页面权限时,侧边栏不能显示模板菜单。 +- [x] 多租户真实账号验收:云浮、揭阳、梅州只能看到自己租户或 `PUBLIC` 入口。 +- [x] 公文列表数据隔离:同一租户下两个公文入口分别进入时,列表数据不能串入口。 +- [x] 公文详情页侧栏:确认不出现平台 Sidebar 和公文工作区 Sidebar 双侧栏。 +- [x] 入口模块管理页真实表单验收:新建、编辑、功能勾选、租户回显必须跑 Playwright。 +- [x] 上传页真实表单验收:从入口进入后,选择文档类型和二级分组提交,后端落库字段正确。 +- [x] 规则分组页真实页面验收:入口 A/B 切换后树隔离,一级分组无绑定入口,二级分组绑定弹窗可用。 +- [x] 评查命中验收:上传带二级分组的文档后启动评查,确认按该二级分组命中规则集。 + +当前暂缓硬改: + +- [ ] `一级分组创建时必须有 entry_module_id` 仍保留兼容口径,避免旧全局分组或历史数据立即断链。下一轮只先补告警和数据巡检,不直接硬拦。 + +### 14.10.4 执行记录 2026-05-24 + +- [x] 清理 Playwright 和手工验收产生的测试入口模块、测试业务大类、测试规则分组。 +- [x] 测试数据清理采用软删除,未硬删历史文档,避免破坏审计记录和外键引用。 +- [x] 已软删除测试入口模块 31 个:`37,39-68`。 +- [x] 已软删除测试业务大类 24 个:`24-47`。 +- [x] 已软删除测试规则分组 71 个:`52-122`。 +- [x] 已软删除入口租户关联 34 条、规则分组绑定 3 条。 +- [x] 反查验证:未删除测试入口模块 0 个、未删除测试业务大类 0 个、未删除测试规则分组 0 个、测试入口有效租户关联残留 0 条、测试分组有效规则绑定残留 0 条。 +- [x] 修复入口模块列表“业务范围”列全部显示“待配置”的问题。 +- [x] 根因确认:数据库中合同评查、案卷智能评查、内部公文已有业务范围绑定,但 `EntryModulesClient.tsx` 把业务范围列写死为“待配置”,后端入口模块列表也没有返回业务范围摘要。 +- [x] 后端 `EntryModuleVO` 增加 `business_scope`,入口模块列表和详情返回业务大类数量、业务类型数量、大类名称列表。 +- [x] `entryModuleAdminServiceImpl.py` 的 `business_scope` 查询兼容两种历史结构:通过 `leaudit_document_types.entry_module_id` 绑定业务大类,以及通过一级规则分组 `entry_module_id` 统计二级业务类型。 +- [x] 前端 `EntryModule` 类型增加 `business_scope`。 +- [x] 前端新增 `summarizeBusinessEntryScope()`,入口模块列表按真实业务范围展示,例如“建设工程合同、买卖合同、借款合同 等 10 类 / 覆盖 10 个业务类型”。 +- [x] 真实数据库只读验证:合同评查 `10` 个业务大类、`10` 个业务类型;案卷智能评查 `10` 个业务大类、`10` 个业务类型;内部公文 `1` 个业务大类、`1` 个业务类型;智慧法务助手和交叉评查当前未配置业务范围,显示“待配置”符合数据事实。 +- [x] 回归验证:`node --test --experimental-strip-types tests/govdoc-audit/business-entry-ui.test.mts` 结果 `7 pass / 0 fail`。 +- [x] 回归验证:`legal-platform-frontend` 下 `npx tsc --noEmit --pretty false` 通过。 +- [x] 回归验证:`.venv/bin/python -m py_compile fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py` 通过。 +- [x] 回归验证:目标 eslint 通过,`0 error / 0 warning`。 +- [x] RBAC 数据调整:删除 `省级管理员 / provincial_admin` 角色。 +- [x] RBAC 删除级联清理:`user_role` 1 条、`role_permissions` 94 条、`role_route` 29 条。 +- [x] 将 `000` 对应用户调整为系统超级管理员:当前库中该用户为 `sso_users.id=5, sub=000, username=admin`。 +- [x] RBAC 反查验证:`provincial_admin` 剩余 0 个;`000` 用户当前只绑定 `super_admin / 系统超级管理员 / data_scope=ALL`。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 验收入口模块编辑页和上传页:`LEAUDIT_FRONTEND_URL=http://127.0.0.1:5193 node /tmp/leaudit-playwright-entry-upload-management-v1.js`,结果 `16 pass / 0 fail`。 +- [x] 入口模块编辑页验收覆盖:4 步表单、菜单模板回显、功能勾选回显、PUBLIC 租户回显、业务范围回显。 +- [x] 上传页验收覆盖:从入口上下文进入后按入口加载业务大类和业务类型,显示所属业务入口,上传接口和文档详情接口返回正确 `entryModuleId/typeId/groupId/tenantCode`。 +- [x] 修复上传页单一业务类型时查不到二级分组的问题:`FilesUploadClient.tsx` 不再只在 `childDocumentTypeIds.length > 1` 时批量查询二级分组。 +- [x] 后端文档上传、列表、详情 VO 返回 `entryModuleId`,方便前端和测试确认文档入口归属。 +- [x] 修复公文详情页双侧栏风险:`/govdoc/detail/...` 和 `/govdoc-audit/detail/...` 不再渲染平台 Sidebar,只保留公文工作区布局。 +- [x] 回归验证:`.venv/bin/python -m py_compile fastapi_modules/fastapi_leaudit/domian/vo/documentVo.py fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py` 通过。 +- [x] 回归验证:`legal-platform-frontend` 下 `npx tsc --noEmit --pretty false` 通过。 +- [x] 回归验证:目标 eslint 通过,`0 error / 1 warning`,warning 为 `files-upload.ts` 被 eslint ignore,非本次阻塞。 +- [x] 本轮 Playwright 临时数据已清理:`PW入口编辑上传-pwui%`、`pw.root.pwui%`、`pw.child.pwui%`、`pw.type.pwui%`、`pw-ui-upload-pwui%` 有效残留均为 0。 +- [x] 环境记录:`./leaudit.sh` 本轮出现 pidfile/后台进程状态不稳定,真实验收改用 TTY 手动启动后端 `run.py` 和前端 `npm run dev:dev`,Playwright 统一访问 `http://127.0.0.1:5193`。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 验收规则分组页:`LEAUDIT_FRONTEND_URL=http://127.0.0.1:5193 node /tmp/leaudit-playwright-rule-groups-scope-v1.js`,结果 `21 pass / 0 fail`。 +- [x] 规则分组页验收覆盖:入口 A/B 树隔离、请求带 `entry_module_id`、一级分组不显示“配置规则”、后端拒绝一级分组绑定规则集、二级分组绑定弹窗可打开并保存。 +- [x] 规则分组页验收发现一个非产品 BUG:临时脚本第一次按旧弹窗类名 `.modal-content/[role=dialog]` 断言失败;当前页面实际使用 `.rg-modal`,修正脚本后通过。 +- [x] 规则分组 Playwright 临时数据已清理:`PW规则分组入口%`、`pw.rg.type.%`、`pw.rg.%`、`note like '%pwrg%'` 有效残留均为 0。 +- [x] 使用 Playwright 真实账号 `000/admin06111` 验收公文入口深度链路:`LEAUDIT_FRONTEND_URL=http://127.0.0.1:5193 node /tmp/leaudit-playwright-govdoc-entry-scope-v1.js`,结果 `17 pass / 0 fail`。 +- [x] 公文入口深度验收覆盖:创建 A/B 公文入口、创建 A/B 公文业务类型、A/B 公文列表请求带 `entry_module_id`、A/B 列表数据不串、标题使用当前入口模块名称、公文上传链接携带 `entryModuleId/documentTypeIds`、公文上传落库携带 `entry_module_id/type_id`、公文详情页不渲染平台 Sidebar。 +- [x] 修正公文 Playwright 验收脚本:不再用 `request.postData()` 判断 multipart 表单,因为该方式对文件上传体不稳定;改为上传后解析新 `documentId` 并查询数据库验证 `leaudit_documents.entry_module_id/type_id`。 +- [x] 公文 Playwright 临时数据已清理:`PW公文入口%`、`pw.govdoc.type.%`、`pw-govdoc-%` 有效文档残留均为 0。 +- [x] 发现并记录一个非阻塞清理差异:公文删除接口会软删 `leaudit_documents`,但 `leaudit_document_files` 中历史测试文件记录仍保持 `deleted_at is null`;当前列表以文档主表删除态过滤,不影响入口隔离验收,后续如要严格清理可单独优化删除服务。 +- [x] 使用 Playwright 真实账号验收多租户入口可见性和普通权限:`LEAUDIT_FRONTEND_URL=http://127.0.0.1:5193 node /tmp/leaudit-playwright-multitenant-entry-scope-v1.js`,结果 `37 pass / 0 fail`。 +- [x] 多租户验收账号:`yf001/yfyc06111`、`jy001/jyyc06111`、`mz001/mzyc06111`、`001/gdyc06111`。 +- [x] 多租户验收覆盖:云浮只看 `合同评查/案卷智能评查/内部公文`;揭阳只看 `合同评查/案卷智能评查/内部公文/交叉评查`;梅州地区管理员看 `合同评查/案卷智能评查/内部公文/智慧法务助手/交叉评查`;普通用户 `001` 看不到 `智慧法务助手`。 +- [x] 权限验收覆盖:普通用户 `001` 首页不显示系统设置按钮,直调 `/api/v3/entry-modules` 返回 403。 +- [x] 使用 Playwright APIRequestContext + 数据库只读查询验收评查命中链路:真实账号 `mz001/mzyc06111` 上传 `legal-platform-frontend/public/testWork/(最终版)智慧法务平台建设采购项目合同(1).docx`,传入 `typeId=1/groupId=2/entryModuleId=1/tenant_code=MZ/autoRun=true`。 +- [x] 评查命中验收结果:上传生成 `documentId=232/runId=110`,`leaudit_documents` 写入 `type_id=1/group_id=2/entry_module_id=1/tenant_code=MZ/current_run_id=110`。 +- [x] 规则集命中数据库证据:`leaudit_audit_runs.id=110` 写入 `rule_set_id=126/rule_version_id=500/group_id_snapshot=2/rule_binding_id_snapshot=101/tenant_code=MZ/scope_type_snapshot=TENANT`,符合 `leaudit_rule_group_bindings.group_id=2` 下梅州租户绑定。 +- [x] 使用 Playwright 真实账号 `001/gdyc06111` 验收模板页面权限过滤:进入 `合同评查` 后 URL 为 `/documents/list?entryModuleId=1&documentTypeIds=...`,侧栏显示 `文件上传/文档列表`,不显示 `合同管理/模板搜索/模板列表`。 +- [x] 模板权限验收补充证据:`001` 为 `common` 角色,无 `contract_template:*` 和 `entry_module:*` 权限;`/api/auth/session-data` 返回的合同入口 `features` 已被裁剪为 `home/documents/upload/rules/rule_groups`,`permissionMap` 不含 `/contract-template` 路由。 +- [x] RBAC 权限数据收口:已按“入口模块只能系统超级管理员维护”口径移除 `admin / 地区管理员` 的 `entry_module:create/update/delete/image/list/detail` 权限和 `/entry-modules` 菜单。 +- [x] 新增可重复执行 SQL:`scripts/创建sql/rbac_entry_module_super_admin_only.sql`,用于保证 `super_admin` 保留入口模块权限,同时移除 `admin/provincial_admin` 的入口模块权限和菜单。 +- [x] 修复首页系统设置按钮跳转:不再固定跳 `/entry-modules`,而是跳当前用户有权限的第一个设置子菜单;没有任何设置子菜单时不显示系统设置按钮。 +- [x] RBAC 收口真实验收:`mz001/mzyc06111` 登录后无 `entry_module:*` 权限,直调 `/api/v3/entry-modules` 返回 403,`settingsChildren` 不含 `/entry-modules`。 +- [x] RBAC 收口真实验收:`000/admin06111` 登录后仍有入口模块 6 个权限,直调 `/api/v3/entry-modules` 返回 200,`settingsChildren` 包含 `/entry-modules`。 + +### 14.10.5 当前最新状态 2026-05-24 + +当前已完成并验证: + +- [x] 入口模块列表业务范围列已经接真实后端摘要,不再统一显示“待配置”。 +- [x] 合同评查、案卷智能评查、内部公文的业务范围摘要和当前数据库绑定一致。 +- [x] 智慧法务助手、交叉评查当前没有绑定业务大类,所以继续显示“待配置”是正确状态。 +- [x] 测试入口模块和测试业务大类已经清理,不会继续污染入口模块管理页和业务大类管理页。 +- [x] `000/admin06111` 对应账号已变成系统超级管理员,后续 Playwright 验收使用该账号时具备系统级管理权限。 +- [x] `provincial_admin` 已删除,后续计划和验收不要再依赖省级管理员这个角色。 +- [x] 入口模块管理页和上传页已经完成真实 Playwright 验收,上传链路能落 `entry_module_id/type_id/group_id/tenant_code`。 +- [x] 规则分组页已经完成真实 Playwright 验收,入口 A/B 不串树,一级不绑定规则,二级绑定弹窗可用。 +- [x] 公文详情页双侧栏代码风险已修复,并已用真实公文详情页面 Playwright 确认。 +- [x] 多租户真实账号验收已完成,云浮、揭阳、梅州入口可见性符合当前入口模块租户分配和 RBAC 菜单权限。 +- [x] 模板页面权限过滤已完成真实 Playwright 验收,普通用户没有模板页面权限时,即使进入合同入口也不显示模板菜单。 +- [x] 评查命中验收已完成,普通文档上传后按 `document.group_id -> leaudit_rule_group_bindings -> rule_set/current_version_id` 命中租户级规则集。 + +后续仍需继续验收: + +- [x] RBAC 权限数据收口:已从 `admin / 地区管理员` 移除入口模块管理权限,当前只有系统超级管理员可以维护入口模块。 + +### 14.10.6 下一轮执行顺序 + +前置调整: + +```text +真实前端 Playwright 全量验收前,先执行入口模块和文档类型的 UI/交互优化计划: +docs/superpowers/plans/2026-05-23-business-entry-ux-optimization.md +``` + +原因: + +```text +当前“入口模块管理 + 文档类型管理 + 规则分组 + 上传”的技术语义学习成本过高。 +如果先写真实前端测试,会把当前复杂交互固化下来。 +应先把页面统一成“业务入口、业务大类、业务类型、规则配置”的用户语义,再做真实 Playwright 验收。 +``` + +按下面顺序继续,不要先碰评查引擎: + +1. P0:入口模块管理页 Playwright 验收。 + + 验收内容: + + ```text + 新建入口 -> 选择菜单模板 -> 勾选功能 -> 分配租户 -> 保存 -> 列表回显 -> 编辑回显 + ``` + + 输出要求: + + ```text + 已完成。继续维护时如果页面字段或回显错,先修前端表单和接口字段映射,不改运行时评查逻辑。 + ``` + +2. P1:上传页真实表单 Playwright 验收。 + + 验收内容: + + ```text + 从入口模块进入上传页 -> 文件上传菜单排第二 -> 选择文档类型 -> 选择二级分组 -> 提交 + ``` + + 输出要求: + + ```text + 已完成。验收确认数据库或接口返回里存在 entry_module_id/type_id/group_id/tenant_code。 + ``` + +3. P2:规则分组页 Playwright 验收。 + + 验收内容: + + ```text + 入口 A 只看到 A 的一级分组 + 入口 B 只看到 B 的一级分组 + 一级分组不出现绑定规则入口 + 二级分组可以打开绑定弹窗并保存 + ``` + + 输出要求: + + ```text + 已完成。验收确认前端透传 `entryModuleId`,后端列表过滤生效,一级/二级规则绑定边界正确。 + ``` + +4. P3:公文入口深度验收。 + + 验收内容: + + ```text + 公文列表按 entry_module_id 隔离 + 公文上传能从入口模块进入 + 公文详情页不出现双侧栏 + ``` + + 输出要求: + + ```text + 如果列表串数据,优先查 govdoc API 请求参数和 GovdocServiceImpl 查询过滤。 + ``` + +5. P4:多租户真实账号验收。 + + 验收内容: + + ```text + 云浮用户只看到云浮或 PUBLIC 入口 + 揭阳用户只看到揭阳或 PUBLIC 入口 + 梅州用户只看到梅州或 PUBLIC 入口 + 没有入口模块管理权限的租户用户 UI 不显示管理能力,接口返回 403 + ``` + + 输出要求: + + ```text + 如果缺少真实账号,先用现有 RBAC/租户数据造最小测试账号,并记录账号和租户。 + ``` + +6. P5:评查命中验收。 + + 验收内容: + + ```text + 上传带二级分组的文档 -> 绑定该二级分组规则集 -> 启动评查 -> 确认命中该规则集 + ``` + + 输出要求: + + ```text + 这里只验证 group_id -> leaudit_rule_group_bindings -> rule_set 主链路,不重构评查引擎。 + ``` + +### 14.10.7 下一轮可并行安排 + +可以拆成 3 个并行工作流。当前 3 个工作流均已完成,本节保留为后续复盘参考: + +- [x] 工作流 A:入口模块管理页 + 上传页 Playwright 验收,主要看表单和字段落库。 +- [x] 工作流 B:规则分组页 + 公文入口深度验收,主要看入口上下文过滤和侧栏。 +- [x] 工作流 C:多租户真实账号 + 模板权限过滤 + 评查命中验收,主要看权限、租户和运行时规则命中。 + +并行约束: + +- [x] 三个工作流都必须先执行 `./leaudit.sh status`,确认后端、前端、Worker、Beat 运行。 +- [x] UI 验收必须使用 Playwright,账号优先使用 `000/admin06111`,多租户验收再补具体租户账号。 +- [x] 每个工作流完成后都要回写本计划文档的执行记录。 +- [x] 发现 BUG 先补最小复现脚本,再修代码,最后跑对应 Playwright 或 pytest 回归。 + +### 14.11 建议提交顺序 + +1. 数据库迁移脚本。 +2. 后端 DTO/VO 和入口模块服务。 +3. 首页入口返回和前端入口上下文。 +4. 侧边栏菜单生成逻辑。 +5. 入口模块管理页菜单模板和功能勾选。 +6. 文档上传和列表入口模块归属。 +7. 公文列表入口模块过滤。 +8. 规则分组和规则绑定校验。 +9. 删除名称包含“合同/公文”的旧判断。 +10. 跑完整验收清单。 + +### 14.12 暂不执行的任务 + +- [ ] 暂不做同一个入口模块不同租户不同功能清单。 +- [ ] 暂不删除旧地区字段。 +- [ ] 暂不删除旧规则类型绑定表。 +- [ ] 暂不重写评查运行引擎。 +- [ ] 暂不把入口模块变成权限系统。 + +### 14.13 下一阶段收口计划:entry_module_id 强一致性 + +#### 14.13.1 先把概念说清楚 + +`entry_module_id` 不是给用户看的新概念,它在前端应该叫“业务入口”或“工作台”。 + +它的作用只有一个:让系统知道一条数据属于哪个入口模块。 + +如果没有 `entry_module_id`,系统只能靠下面这些不稳定方式猜: + +```text +入口名字里有没有“合同” +当前 URL 是不是 /govdoc +文档类型刚好属于哪个入口 +规则分组刚好挂在哪个父节点下面 +``` + +这些猜法会导致同一个租户下多个入口互相串数据,例如: + +```text +合同入口能看到案卷文档 +公文入口侧边栏混入普通文件上传 +规则分组 A/B 入口互相出现 +上传后评查命中错规则集 +``` + +所以新链路必须明确落字段: + +```text +入口模块 leaudit_entry_modules.id + -> 业务大类/一级分组 leaudit_evaluation_point_groups.entry_module_id + -> 业务类型/二级分组 group_id + -> 文档 leaudit_documents.entry_module_id + group_id + -> 评查按 group_id 命中规则绑定 +``` + +用户理解口径: + +```text +我从哪个业务入口进来,上传、列表、规则配置就只看这个入口下的数据。 +``` + +开发理解口径: + +```text +entry_module_id 是入口隔离字段。 +tenant_code 管租户边界。 +group_id 管规则命中。 +type_id 管文档分类。 +features/menu_profile 管菜单显示。 +``` + +#### 14.13.2 当前不直接强拦的原因 + +当前代码里“一级业务大类必须有 `entry_module_id`”还没有完全强拦,是刻意保留兼容。 + +原因: + +```text +老数据里可能还有全局一级分组 +老文档可能只能从 type_id 或 group_id 推导入口 +如果现在直接 400,可能会把旧规则配置、旧上传链路或历史列表打断 +``` + +因此下一阶段不能一步到位硬改,必须按下面顺序推进: + +```text +先巡检旧数据 +再修复或回填孤儿数据 +再加后端软提示/日志 +最后才把新建和编辑一级业务大类改成必须有入口模块 +``` + +#### 14.13.3 实现顺序 + +1. 数据巡检。 + + 执行只读巡检脚本: + + ```bash + psql "$DATABASE_URL" -f scripts/创建sql/verify_entry_module_menu_profile.sql + ``` + + 重点看这几类结果: + + ```text + 文档 entry_module_id 为空 + 文档 entry_module_id 和 group/type 推导不一致 + 重复二级分组 + 一级分组 entry_module_id 为空 + 非法 menu_profile/features + ``` + +2. 旧数据处理。 + + 如果一级分组没有 `entry_module_id`,先按可推导关系回填: + + ```text + 一级分组有 document_type_id -> 用 leaudit_document_types.entry_module_id 回填 + 一级分组下二级分组有 document_type_id -> 用二级分组对应文档类型的 entry_module_id 回填 + 确实无法推导 -> 先列清单人工判断,不自动乱填 + ``` + + 注意: + + ```text + 不允许为了清零数据随便塞 entry_module_id=1 + 不允许把跨入口共用的旧分组直接强绑到某一个入口 + ``` + +3. 后端创建校验收紧。 + + 文件: + + ```text + fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py + ``` + + 目标: + + ```text + 新建一级业务大类 pid=0 时,必须传 entry_module_id + 新建一级业务大类不允许只靠 document_type_id 反推入口 + 新建二级业务类型 pid!=0 时,继承父级 entry_module_id + 新建二级业务类型必须绑定 document_type_id + 二级业务类型的 document_type_id 所属入口必须和父级入口一致 + ``` + + 兼容策略: + + ```text + 只强拦新建/编辑请求 + 不因为历史数据缺 entry_module_id 导致列表查询直接失败 + ``` + +4. 前端规则配置页补齐入口上下文。 + + 文件: + + ```text + legal-platform-frontend/app/(audit)/rule-groups/RuleGroupsClient.tsx + ``` + + 目标: + + ```text + 从业务入口进入规则配置页时,新增业务大类自动带当前 entryModuleId + 页面顶部显示“当前业务入口:xxx” + 如果没有入口上下文,不允许新增业务大类,只提示从首页业务入口进入 + ``` + + 用户看到的是: + + ```text + 当前业务入口:合同评查 + 新增业务大类时自动归属当前入口 + ``` + + 用户不需要看到: + + ```text + entry_module_id + pid = 0 + group_id + ``` + +5. 上传页保持现有两级选择。 + + 文件: + + ```text + legal-platform-frontend/app/(audit)/files/upload/FilesUploadClient.tsx + ``` + + 目标不变: + + ```text + 先选业务大类 + 再选业务类型 + 提交 entryModuleId/typeId/groupId/tenantCode + ``` + + 这里不要做自动创建业务类型,也不要跳过业务类型选择。 + +6. 验收。 + + 必须使用 Playwright 真实账号验收: + + ```text + 000/admin06111:新增业务大类 -> 新增业务类型 -> 配置规则 -> 上传 -> 列表只看当前入口 + mz001/mzyc06111:不能进入业务入口管理,能使用已分配入口 + yf001/yfyc06111:只能看到云浮已分配入口 + jy001/jyyc06111:只能看到揭阳已分配入口 + ``` + + 数据库验收: + + ```text + leaudit_evaluation_point_groups 一级分组有 entry_module_id + leaudit_evaluation_point_groups 二级分组能通过父级拿到 entry_module_id + leaudit_documents 上传后有 entry_module_id/type_id/group_id/tenant_code + leaudit_audit_runs 按 group_id_snapshot 命中 rule_binding_id_snapshot + ``` + +#### 14.13.4 推荐下一步直接做什么 + +下一步不先改代码,先做一次真实数据库巡检并记录结果。 + +执行顺序: + +```text +1. 运行 verify_entry_module_menu_profile.sql +2. 把异常结果整理到本计划文档 +3. 如果一级分组 entry_module_id 为空数量为 0,再开始后端强校验 +4. 如果不为 0,先补一个只读清单和人工回填 SQL 草案 +5. 回填完成后再改后端校验和前端规则配置页 +``` + +这样做的原因: + +```text +entry_module_id 是隔离字段,一旦强校验加错,会直接影响上传、规则配置、列表过滤和评查命中。 +先把数据状态摸清,再收紧代码,风险最低。 +``` + +#### 14.13.5 巡检记录 2026-05-24 + +已执行: + +```bash +PGPASSWORD='zhfw*123*' psql -h nas.7bm.co -p 54302 -U docauditai_admin -d leaudit_platform -f scripts/创建sql/verify_entry_module_menu_profile.sql +``` + +同时修正巡检脚本字段错误: + +```text +leaudit_documents 没有 filename 字段,实际字段为 normalized_name。 +已把脚本中的 d.filename 改为 d.normalized_name AS document_name。 +``` + +巡检结论: + +```text +必要字段存在: +leaudit_entry_modules.menu_profile +leaudit_entry_modules.features +leaudit_documents.entry_module_id + +必要索引存在: +idx_leaudit_entry_modules_menu_profile +idx_leaudit_documents_entry_module_id + +非法 menu_profile:0 条 +非法 feature 编码:0 条 +重复二级分组:0 条 +文档 entry_module_id 与 group/type 推导不一致:0 条 +``` + +发现的问题: + +```text +案卷智能评查 features 为空 +智慧法务助手 features 为空 +历史文档 entry_module_id 为空:68 条 +其中 65 条可以通过 group/type 推导入口 +其中 3 条公文示例没有 type_id/group_id,暂时无法自动推导入口 +一级业务大类 entry_module_id 为空:14 条 +``` + +68 条历史文档缺入口归属的推导结果: + +```text +可推导为 合同评查 entry_module_id=1:47 条 +可推导为 案卷智能评查 entry_module_id=2:14 条 +可推导为 内部公文 entry_module_id=3:4 条 +无法推导:3 条,均为旧公文示例,type_id/group_id 为空 +``` + +14 条一级业务大类缺入口归属的来源: + +```text +行政卷宗 root.casefile:可通过子业务类型推导为 案卷智能评查 entry_module_id=2 +testmzceshi:测试残留,无子节点、无 document_type_id,需要人工确认是否删除 +12 条 PW*/pw.* 测试业务大类:来自已软删除的 Playwright 临时入口,关联文档类型仍未软删 +``` + +关键判断: + +```text +当前正式 5 个入口本身没有结构性问题。 +真正阻塞强校验的是历史数据和 Playwright 测试残留。 +现在不能直接加“一级业务大类必须有 entry_module_id”的硬拦截,否则旧残留会继续污染巡检,也可能影响旧数据展示。 +``` + +建议下一步: + +```text +1. 先出只读清单 SQL,列出可自动回填的 65 条历史文档和 root.casefile。 +2. 出数据修复 SQL 草案,但先不执行。 +3. Playwright 测试残留建议统一软删:pw.* 文档类型、PW* 规则分组、对应临时入口关系。 +4. testmzceshi 需要人工确认是否删除。 +5. 3 条无 type_id/group_id 的旧公文示例不要自动回填,保留人工处理。 +6. 数据修复完成后,再改后端强校验和前端规则配置页入口上下文。 +``` + +#### 14.13.6 数据修复执行记录 2026-05-24 + +已新增并执行数据修复脚本: + +```text +scripts/创建sql/repair_entry_module_scope_data_20260524.sql +``` + +执行前做了事务回滚演练: + +```text +可回填历史文档:65 条 +可回填一级业务大类:1 条,root.casefile 行政卷宗 +可继承父级入口的二级业务类型:19 条 +可安全软删测试规则分组:25 条 +可补默认功能的入口模块:1 条,案卷智能评查 +``` + +正式执行结果: + +```text +UPDATE 65 +UPDATE 1 +UPDATE 19 +UPDATE 25 +UPDATE 1 +COMMIT +``` + +修复内容: + +```text +65 条历史文档已按 group/type 推导回填 entry_module_id。 +行政卷宗 root.casefile 已回填 entry_module_id=2,归属案卷智能评查。 +行政卷宗及合同正式二级业务类型已继承父级 entry_module_id。 +testmzceshi 和 PW*/pw.* 无引用测试规则分组已软删除。 +案卷智能评查已补齐默认功能:home/documents/upload/rules/rule_groups。 +``` + +修复后巡检结果: + +```text +非法 menu_profile:0 条 +非法 feature 编码:0 条 +文档 entry_module_id 与 group/type 推导不一致:0 条 +重复二级分组:0 条 +一级业务大类 entry_module_id 为空:0 条 +活跃 PW 测试文档类型:0 条 +活跃测试规则分组残留:0 条 +活跃文档类型指向已删除入口:0 条 +``` + +剩余问题: + +```text +仍有 3 条旧公文示例文档 entry_module_id 为空。 +这 3 条同时没有 type_id 和 group_id,无法确定属于哪个入口模块。 +本次没有自动回填,避免把历史公文示例错误塞进内部公文或其他入口。 +``` + +剩余 3 条: + +```text +id=46 公文示例-瑕疵 +id=47 公文示例-瑕疵 +id=48 公文示例-合规-OOXML修正版 +``` + +后续处理建议: + +```text +如果确认它们是内部公文旧测试数据,可以单独回填 entry_module_id=3。 +如果只是历史测试样例,也可以软删除。 +在未确认前,不建议自动处理。 +``` + +#### 14.13.7 旧公文示例回填记录 2026-05-24 + +用户已确认 3 条旧公文示例可以回填。 + +已新增并执行: + +```text +scripts/创建sql/repair_govdoc_sample_entry_module_20260524.sql +``` + +执行条件: + +```text +只更新 id IN (46, 47, 48) +只更新 deleted_at IS NULL +只更新 entry_module_id IS NULL +只更新 engine_type='govdoc' 且 review_scope='govdoc' +只回填 entry_module_id=3,不伪造 type_id/group_id +``` + +执行结果: + +```text +UPDATE 3 +COMMIT +``` + +回填后结果: + +```text +id=46 公文示例-瑕疵 -> entry_module_id=3 +id=47 公文示例-瑕疵 -> entry_module_id=3 +id=48 公文示例-合规-OOXML修正版 -> entry_module_id=3 +``` + +最终巡检结果: + +```text +documents_without_entry_module = 0 +文档 entry_module_id 与 group/type 推导不一致 = 0 +一级业务大类 entry_module_id 为空 = 0 +重复二级分组 = 0 +非法 menu_profile = 0 +非法 feature 编码 = 0 +``` diff --git a/docs/superpowers/plans/2026-05-23-entry-module-phase2-scope-completion.md b/docs/superpowers/plans/2026-05-23-entry-module-phase2-scope-completion.md new file mode 100644 index 0000000..31f69f3 --- /dev/null +++ b/docs/superpowers/plans/2026-05-23-entry-module-phase2-scope-completion.md @@ -0,0 +1,248 @@ +# 入口模块重构第二阶段实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 补齐入口模块到普通文档、上传、规则分组、页面布局的闭环,让用户从某个入口进去后,只看到、上传、配置该入口范围内的业务数据。 + +**Architecture:** 第一阶段已完成入口上下文、菜单 features 过滤、公文列表/上传入口归属。第二阶段继续沿用 `selectedEntryModuleContext`,所有业务页面从该上下文读取 `entryModuleId/documentTypeIds`,后端继续用 `entry_module_id/type_id/group_id/tenant_code` 做数据收口,不新增权限体系。 + +**Tech Stack:** FastAPI、SQLAlchemy 原生 SQL、Next.js、React、现有 RBAC 权限、现有 `leaudit_entry_modules / leaudit_document_types / leaudit_evaluation_point_groups / leaudit_documents` 表。 + +--- + +## 一、执行原则 + +- 不再用入口名称判断业务类型。 +- 不改现有 UI 视觉风格,只补数据范围、参数和必要提示。 +- 不删除旧接口,先补安全约束和兼容字段。 +- 先做普通文档链路,再做规则分组链路,最后处理重复侧边栏和验收。 +- 每一批改完都跑 `py_compile`、`tsc`、目标 `eslint`。 + +## 二、文件责任 + +- `legal-platform-frontend/lib/auth/entry-module-context.ts`:继续作为前端入口上下文唯一读写入口。 +- `legal-platform-frontend/lib/api/legacy/files/documents.ts`:普通文档列表、上传 API 参数补入口模块字段。 +- `legal-platform-frontend/app/(audit)/files/upload/*` 或实际上传客户端文件:上传表单带 `entryModuleId/typeId/groupId`。 +- `legal-platform-frontend/app/(audit)/documents/*` 或实际文档列表客户端文件:文档列表按入口上下文传 `entryModuleId/documentTypeIds`。 +- `fastapi_modules/fastapi_leaudit/controllers/documentController.py`:普通上传接口接收 `entryModuleId`。 +- `fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py`:创建文档写入 `entry_module_id`,校验 `group_id` 是二级分组且属于当前入口。 +- `legal-platform-frontend/app/(audit)/rule-groups/RuleGroupsClient.tsx`:规则分组页读取入口上下文,只展示当前入口分组。 +- `fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py`:分组列表/创建/更新接收或校验入口模块参数。 +- `fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py`:一级/二级分组边界、入口模块归属、绑定二级分组校验。 +- `legal-platform-frontend/components/layout/Layout.tsx`:处理公文详情页内部工作区侧栏和平台 Sidebar 重复问题。 + +--- + +## 三、任务拆分 + +### Task 1:普通文档上传写入入口模块 + +**目标:** 用户从入口模块进入上传页时,上传出来的文档写入 `entry_module_id/type_id/group_id/tenant_code`。 + +**Files:** +- Modify: `fastapi_modules/fastapi_leaudit/controllers/documentController.py` +- Modify: `fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py` +- Modify: `legal-platform-frontend/lib/api/legacy/files/documents.ts` +- Modify: 实际上传页面客户端,先用 `rg -n "DocumentUpload|uploadDocument|/upload" legal-platform-frontend/app legal-platform-frontend/components` + +- [x] 后端 `UploadDocument` 增加 `entryModuleId: int | None = Form(None)`。 +- [x] `DocumentService.Upload(...)` 增加 `EntryModuleId` 参数。 +- [x] 创建 `LeauditDocument` 后写入 `entry_module_id`。 +- [x] 如果传了 `groupId`,校验该分组 `pid <> 0`。 +- [x] 如果传了 `entryModuleId + groupId`,校验二级分组所属入口等于 `entryModuleId`。 +- [x] 如果没传 `groupId`,只允许唯一二级分组时后端兜底;多个二级分组时报 400,让前端用户明确选择。 +- [x] 前端上传 API 从 `readEntryModuleContext()` 读取 `entryModuleId/documentTypeIds`。 +- [x] 上传表单把 `entryModuleId`、选中的 `typeId`、选中的 `groupId` 一起提交。 + +**验收:** +- 上传成功后数据库 `leaudit_documents.entry_module_id` 有值。 +- 多个二级分组时,不选 `groupId` 不能上传。 +- 传一级分组 ID 时后端返回 400。 + +### Task 2:普通文档列表按入口模块过滤 + +**目标:** 从不同入口进入普通文档列表,只看到当前入口范围的文档。 + +**Files:** +- Modify: `legal-platform-frontend/lib/api/legacy/files/documents.ts` +- Modify: 普通文档列表客户端,先用 `rg -n "listDocuments|getDocuments|documents.searchParams" legal-platform-frontend/app legal-platform-frontend/components` +- Backend already has: `documentController.py` 的 `entry_module_id/type_ids` 和 `documentServiceImpl.py` 的过滤基础。 + +- [x] 文档列表页面读取入口上下文作用域(URL/session,由入口首页写入)。 +- [x] 请求参数带 `entry_module_id`。 +- [x] 请求参数带 `type_ids`,作为入口文档类型范围的兜底过滤。 +- [x] 保留现有搜索、分页、状态过滤,不改 UI。 +- [x] 切换入口模块时清理 `documents.searchParams`,避免旧入口搜索条件污染新入口。 + +**验收:** +- 入口 A 上传的文档不出现在入口 B。 +- 没有入口上下文时,保留原有列表行为。 + +### Task 3:规则分组页按入口模块收口 + +**目标:** 规则分组页只展示当前入口模块下的一级分组和二级分组。 + +**Files:** +- Modify: `legal-platform-frontend/app/(audit)/rule-groups/RuleGroupsClient.tsx` +- Modify: `legal-platform-frontend/app/api/rule-groups/*` +- Modify: `fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py` +- Modify: `fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py` + +- [x] 前端读取 `entryModuleId`。 +- [x] 分组列表请求带 `entry_module_id`。 +- [x] 后端列表用 `entry_module_id` 过滤一级分组。 +- [x] 二级分组根据父级一级分组自然收口。 +- [x] 新建一级分组默认带当前入口 `entry_module_id`。 +- [x] 新建二级分组必须带 `document_type_id`,且文档类型属于当前入口。 +- [x] 编辑二级分组时禁止移动到其他入口的一级分组下。 + +**验收:** +- 合同入口看不到公文入口的分组。 +- 公文入口看不到合同入口的分组。 +- 二级分组不能跨入口挂载。 + +### Task 4:规则绑定二级分组硬校验 + +**目标:** 规则只能绑定二级分组,不能绑定一级分组,也不能跨租户/跨入口污染。 + +**Files:** +- Modify: `fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py` +- Review: `fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py` + +- [x] 保留新接口已有 `pid == 0` 拒绝绑定逻辑。 +- [x] 在绑定保存时再次校验 group 所属入口对当前用户可见。 +- [x] `_load_binding_map` 增加绑定级租户过滤:当前租户、`PUBLIC`、`PROVINCIAL` 可见,其它租户不可见。 +- [x] 旧规则绑定兼容接口只允许唯一可访问二级分组场景写入。 +- [x] 旧接口写入新绑定表时必须带 `tenant_code/scope_type`,保持第一阶段补丁。 + +**验收:** +- 一级分组绑定返回 400。 +- 普通租户看不到其它租户绑定。 +- 全局管理员能看到公共/省级范围绑定。 + +### Task 5:重复侧边栏处理 + +**目标:** 公文详情页不要同时出现平台 Sidebar 和公文工作区 Sidebar。 + +**Files:** +- Modify: `legal-platform-frontend/components/layout/Layout.tsx` +- Review: `legal-platform-frontend/components/govdoc-audit/GovdocAuditResultPage.tsx` + +- [x] 确认哪些公文页面内部有 `GovdocWorkspaceSidebar`。 +- [x] `Layout.tsx` 对公文详情/结果页隐藏平台 Sidebar。 +- [x] 公文列表、上传、概览仍保留平台 Sidebar。 +- [x] 不改公文工作区内部 UI,只处理外层布局冲突。 + +**验收:** +- `/govdoc/audits` 只有平台 Sidebar。 +- `/govdoc/[id]` 或详情页只有公文工作区 Sidebar。 +- 移动端布局不新增横向溢出。 + +### Task 6:前端权限和 UI 一致性复查 + +**目标:** features 只是入口功能编排,不能绕过 RBAC 页面/API 权限。 + +**Files:** +- Review: `legal-platform-frontend/components/layout/Sidebar.tsx` +- Review: `legal-platform-frontend/lib/auth/entry-module-menu.ts` +- Review: `legal-platform-frontend/lib/auth/user-routes.ts` + +- [x] 确认菜单先从 RBAC 路由结果生成,再按 features 过滤。 +- [x] 没有合同模板页面权限时,即使入口启用合同模板 feature,也不显示模板菜单。 +- [x] 没有规则分组权限时,即使入口启用 `rule_groups`,也不显示规则分组菜单。 +- [x] 所有新增提示沿用现有 CSS 变量和组件风格。 + +**验收:** +- 入口 features 不能“放大权限”,只能“收窄菜单”。 + +--- + +## 四、并行安排 + +建议用 subagent 并行: + +- Worker A:Task 1 普通文档上传链路。 +- Worker B:Task 2 普通文档列表过滤。 +- Worker C:Task 3/4 规则分组和绑定后端校验。 +- Worker D:Task 5 重复侧边栏处理。 +- 主线程:整合冲突、跑验证、更新计划文档。 + +注意:Worker A 和 Worker B 可能同时改 `lib/api/legacy/files/documents.ts`,需要一个人先做 API 类型,另一个只改页面调用,避免冲突。 + +--- + +## 五、验证命令 + +后端: + +```bash +python -m py_compile fastapi_modules/fastapi_leaudit/controllers/documentController.py fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py +``` + +前端: + +```bash +cd legal-platform-frontend +npx tsc --noEmit --pretty false +npx eslint --no-ignore lib/auth/entry-module-context.ts lib/auth/entry-module-menu.ts components/layout/Sidebar.tsx components/layout/Layout.tsx +``` + +手工验收: + +- 创建一个名称不含“合同”的合同入口,启用合同模板功能,检查模板搜索/模板列表显示。 +- 创建一个名称不含“公文”的公文入口,启用公文功能,检查公文列表/上传显示。 +- 从入口 A 上传普通文档,入口 B 不应看到。 +- 从入口 A 进入规则分组,只看到入口 A 的一级/二级分组。 +- 尝试把规则绑到一级分组,应失败。 +- 公文详情页不出现双侧栏。 + +执行记录(2026-05-23): + +- 已跑后端目标编译:`python -m py_compile ...`,通过。 +- 已跑前端类型检查:`npx tsc --noEmit --pretty false`,通过。 +- 已跑目标 eslint:0 error,剩余 31 个 warning 为既有未使用变量 / any / hook dependency 类警告。 +- 已用 Playwright 真实账号 `000/admin06111` 做首页和侧边栏 smoke: + - 登录成功。 + - 点击入口后进入 `/documents/list?entryModuleId=...&documentTypeIds=...`。 + - 侧边栏顺序为:首页、文件上传、文档列表、规则管理。 + - 文档列表没有重复。 + - 上传文档按钮可见。 +- 已用 Playwright 真实后端链路跑优先项 `2/3/4/5`:`node /tmp/leaudit-playwright-priority-2-5-v3.js`,结果 `25 pass / 0 fail`。 + - 上传携带 `entryModuleId/groupId` 成功,文档详情返回正确 `typeId/groupId/tenantCode`。 + - 文档列表按入口 A/B 隔离通过。 + - 规则分组按入口 A/B 隔离通过。 + - 一级分组绑定规则集返回 400。 + - 二级分组绑定规则集返回 200。 + - 无入口模块创建/编辑/删除权限用户直接调接口返回 403。 +- 修复一次 Playwright 暴露的后端 500: + - 文件:`fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py` + - 方法:`_get_binding_row` + - 原因:SQL 文本没有使用 f-string,`{access_filter}` 原样发送到 PostgreSQL。 + - 修复:把查询文本改为 f-string,入口模块/租户可见性过滤正常注入。 +- 已跑后端规则绑定范围单测:`pytest -q tests/test_rule_group_binding_scope.py`,结果 `4 passed`。 +- 已重新跑前端类型检查:`npx tsc --noEmit --pretty false`,通过。 +- 已重新跑目标 eslint:0 error,剩余 6 个 warning,为既有 ``、未使用变量类提示。 +- 仍需继续做真实浏览器页面级验收: + - 入口模块管理页功能勾选保存和回显。 + - 上传页真实表单选择文档类型、二级分组后提交。 + - 规则分组页面真实 UI 下只展示当前入口范围。 + - 公文列表、公文上传、公文详情页侧边栏真实页面检查。 + - 多租户可见性需要用不同租户账号逐个验证。 + +下一步执行顺序: + +1. Playwright 页面级验收入口模块管理页:新建/编辑入口,检查 `menu_profile/features/tenants` 保存和回显。 +2. Playwright 页面级验收上传页:确认文件上传在 UI 上第二位,选择文档类型和二级分组后真实提交。 +3. Playwright 页面级验收规则分组页:入口 A/B 切换后页面树、绑定按钮、绑定弹窗范围正确。 +4. Playwright 页面级验收公文入口:名称不含“公文”但配置公文功能时,公文列表/上传可进入且标题不写死。 +5. 多租户账号验证:分别用云浮、揭阳、梅州或可用测试账号验证入口模块可见性和入口管理权限。 +6. 根据页面级验收结果修复前端展示问题,再回跑 `tsc`、目标 eslint、Playwright。 + +--- + +## 六、暂缓项 + +- 暂不删除旧 `leaudit_rule_type_bindings` 表。 +- 暂不重写评查运行引擎。 +- 暂不做同一入口模块按租户覆盖 features。 +- 暂不大改页面视觉,只做现有 UI 风格内的补充。 diff --git a/docs/superpowers/plans/2026-05-23-qichacha-migration.md b/docs/superpowers/plans/2026-05-23-qichacha-migration.md new file mode 100644 index 0000000..06656cb --- /dev/null +++ b/docs/superpowers/plans/2026-05-23-qichacha-migration.md @@ -0,0 +1,71 @@ +# Qichacha Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Migrate the legacy Qichacha company verification module into the current LeAudit backend and keep the existing frontend company-info modal working. + +**Architecture:** Add a `[QICHACHA]` TOML settings section, a new `qcc_company_info` active-record model, DTO/VO objects, a service interface plus implementation, and a small HTTP client wrapper for Qichacha signing and API parsing. Controllers expose `/api/v2/qichacha/*` using unified `Result[...]`; the frontend wrapper unwraps both the new `Result` response and the old raw legacy shape. + +**Tech Stack:** FastAPI, SQLAlchemy async ORM, Pydantic v2, httpx, pytest, Next.js TypeScript. + +--- + +### Task 1: Configuration And Response Contract + +**Files:** +- Modify: `app.toml` +- Modify: `fastapi_admin/config/_settings.py` +- Modify: `fastapi_admin/config/__init__.py` +- Create: `tests/test_qichacha_config_client.py` + +- [ ] Write failing tests proving `QICHACHA_*` settings are exported and the client generates the expected MD5 token. +- [ ] Add `QichachaSettings` and `[QICHACHA]` placeholders. +- [ ] Implement `QichachaClient` with signing, retry-friendly GET calls, and response validation. +- [ ] Run `pytest tests/test_qichacha_config_client.py -q`. + +### Task 2: Backend Domain And Cache Service + +**Files:** +- Create: `fastapi_common/fastapi_common_web/exception/QichachaException.py` +- Create: `fastapi_modules/fastapi_leaudit/domian/Dto/qichachaDto.py` +- Create: `fastapi_modules/fastapi_leaudit/domian/vo/qichachaVo.py` +- Create: `fastapi_modules/fastapi_leaudit/models/qichachaCompanyInfo.py` +- Create: `fastapi_modules/fastapi_leaudit/services/qichachaService.py` +- Create: `fastapi_modules/fastapi_leaudit/services/impl/qichachaServiceImpl.py` +- Modify: `fastapi_modules/fastapi_leaudit/models/__init__.py` +- Modify: `fastapi_modules/fastapi_leaudit/services/__init__.py` +- Create: `tests/test_qichacha_service.py` + +- [ ] Write failing tests for cache hit, stale refresh, force refresh, and dishonesty count mapping. +- [ ] Implement model classmethods for keyword lookup and upsert. +- [ ] Implement service interface and implementation returning VO objects. +- [ ] Run `pytest tests/test_qichacha_service.py -q`. + +### Task 3: API Routes, Permissions, SQL + +**Files:** +- Create: `fastapi_modules/fastapi_leaudit/controllers/qichachaController.py` +- Modify: `fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py` +- Modify: `scripts/创建sql/user_rbac_seed.sql` +- Create: `scripts/创建sql/schema_qichacha_company_info.sql` + +- [ ] Add authenticated routes for `/v2/qichacha/company`, `/enterprise`, `/dishonesty`, `/batch`, `/status`. +- [ ] Add action permissions `qichacha:company:query` and `qichacha:status:read` without creating a route/menu entry. +- [ ] Add SQL schema for `qcc_company_info`. +- [ ] Run backend import and focused pytest checks. + +### Task 4: Frontend Compatibility + +**Files:** +- Modify: `legal-platform-frontend/lib/api/legacy/corporate-information/qichacha.ts` + +- [ ] Add a local unwrap helper that returns `response.data.data` for new `Result` responses and raw `response.data` for legacy responses. +- [ ] Use it in `queryCompanyInfo`, `queryEnterpriseInfo`, and `queryDishonestyInfo`. +- [ ] Run TypeScript or lint check for the changed file scope. + +### Task 5: Verification + +- [ ] Run focused backend tests: `pytest tests/test_qichacha_config_client.py tests/test_qichacha_service.py -q`. +- [ ] Run Python compile/import checks for new backend files. +- [ ] Run frontend lint/type verification if available. +- [ ] Review `git diff` to ensure no unrelated dirty files were reverted. diff --git a/docs/规则编辑/backups/frontend-rule-editor-smoke-cleanup-20260521-225643.json b/docs/规则编辑/backups/frontend-rule-editor-smoke-cleanup-20260521-225643.json new file mode 100644 index 0000000..2e8683c --- /dev/null +++ b/docs/规则编辑/backups/frontend-rule-editor-smoke-cleanup-20260521-225643.json @@ -0,0 +1,128 @@ +{ + "rule_set": { + "id": 127, + "rule_type": "contract.entrust", + "rule_name": "通用委托合同", + "domain_type": "contract", + "description": "依据《中华人民共和国民法典》合同编·通则(第467、470、490条)及委托合同章(第919-936条)。", + "entry_module": null, + "current_version_id": 655, + "status": "active", + "is_builtin": false, + "owner_user_id": null, + "created_at": "2026-05-21 09:46:17.228475+00:00", + "updated_at": "2026-05-21 14:54:33.571988+00:00", + "deleted_at": null, + "region": "MZ", + "tenant_code": "MZ", + "scope_type": "TENANT", + "source_rule_set_id": 22, + "tenant_name_snapshot": "梅州" + }, + "versions": [ + { + "id": 509, + "rule_set_id": 127, + "version_no": "2.0", + "version_seq": 31, + "status": "deprecated", + "source_type": "oss_yaml", + "dsl_format": "yaml", + "oss_url": "rules/contract.entrust/2.0/rules.yaml", + "file_sha256": "5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17", + "file_size": 38821, + "local_cache_path": null, + "metadata_type_id": "contract.entrust", + "metadata_name": "通用委托合同", + "metadata_version": "2.0", + "change_note": "从 leaudit-oss-yaml-files 全量导入", + "editor_user_id": null, + "publisher_user_id": null, + "published_at": "2026-05-21 14:19:42.573203+00:00", + "created_at": "2026-05-21 14:19:42.573203+00:00", + "updated_at": "2026-05-21 14:54:33.571988+00:00", + "deleted_at": null, + "tenant_code_snapshot": "MZ", + "scope_type_snapshot": "TENANT", + "source_version_id": null + }, + { + "id": 653, + "rule_set_id": 127, + "version_no": "v32", + "version_seq": 32, + "status": "deprecated", + "source_type": "oss_yaml", + "dsl_format": "yaml", + "oss_url": "rules/contract.entrust/v32/rules.yaml", + "file_sha256": "a1a2bd60b6e2508791a08d68f395d19907c5abd886994b39f5cbd50dea430425", + "file_size": 43686, + "local_cache_path": null, + "metadata_type_id": "contract.entrust", + "metadata_name": "通用委托合同", + "metadata_version": "", + "change_note": "保存 通用委托合同/合同/通用委托合同 规则配置", + "editor_user_id": 5, + "publisher_user_id": 5, + "published_at": "2026-05-21 14:44:19.989164+00:00", + "created_at": "2026-05-21 14:44:15.414578+00:00", + "updated_at": "2026-05-21 14:54:33.571988+00:00", + "deleted_at": null, + "tenant_code_snapshot": "MZ", + "scope_type_snapshot": "PROVINCIAL", + "source_version_id": null + }, + { + "id": 654, + "rule_set_id": 127, + "version_no": "v33", + "version_seq": 33, + "status": "deprecated", + "source_type": "oss_yaml", + "dsl_format": "yaml", + "oss_url": "rules/contract.entrust/v33/rules.yaml", + "file_sha256": "e21a2a618cdab45b447f8ff5e6fdfbf92b2f448c30df90bae579015da164e8e6", + "file_size": 43965, + "local_cache_path": null, + "metadata_type_id": "contract.entrust", + "metadata_name": "通用委托合同", + "metadata_version": "", + "change_note": "保存 通用委托合同/合同/通用委托合同 规则配置", + "editor_user_id": 5, + "publisher_user_id": 5, + "published_at": "2026-05-21 14:53:04.545640+00:00", + "created_at": "2026-05-21 14:52:59.952306+00:00", + "updated_at": "2026-05-21 14:54:33.571988+00:00", + "deleted_at": null, + "tenant_code_snapshot": "MZ", + "scope_type_snapshot": "PROVINCIAL", + "source_version_id": null + }, + { + "id": 655, + "rule_set_id": 127, + "version_no": "v34", + "version_seq": 34, + "status": "published", + "source_type": "oss_yaml", + "dsl_format": "yaml", + "oss_url": "rules/contract.entrust/v34/rules.yaml", + "file_sha256": "133d936d52666857c5b043b5910d0dcc04b1db2da2ac2e0ee03bb905d49f1c04", + "file_size": 44276, + "local_cache_path": null, + "metadata_type_id": "contract.entrust", + "metadata_name": "通用委托合同", + "metadata_version": "", + "change_note": "保存 通用委托合同/合同/通用委托合同 规则配置", + "editor_user_id": 5, + "publisher_user_id": 5, + "published_at": "2026-05-21 14:54:33.571988+00:00", + "created_at": "2026-05-21 14:54:30.387264+00:00", + "updated_at": "2026-05-21 14:54:33.571988+00:00", + "deleted_at": null, + "tenant_code_snapshot": "MZ", + "scope_type_snapshot": "PROVINCIAL", + "source_version_id": null + } + ] +} \ No newline at end of file diff --git a/docs/规则编辑/backups/rule-domain-before-reset-20260521-221930.sql b/docs/规则编辑/backups/rule-domain-before-reset-20260521-221930.sql new file mode 100644 index 0000000..409c3f7 --- /dev/null +++ b/docs/规则编辑/backups/rule-domain-before-reset-20260521-221930.sql @@ -0,0 +1,527 @@ +-- Rule domain backup before reset +-- generated_at: 2026-05-21T22:19:30 +-- rule_sets: 147 +-- rule_versions: 371 + +-- This file is an audit snapshot, not an automatic restore script. +-- Use the rows below to inspect pre-reset IDs, current_version_id, oss_url and sha. + +-- rule_set id=21 tenant_code=PUBLIC rule_type=contract.construction.general current_version_id=311 status=active deleted_at=None +-- rule_set id=22 tenant_code=PUBLIC rule_type=contract.entrust current_version_id=320 status=active deleted_at=None +-- rule_set id=23 tenant_code=PUBLIC rule_type=contract.evaluation.delegation current_version_id=321 status=active deleted_at=None +-- rule_set id=24 tenant_code=PUBLIC rule_type=contract.gift.charity current_version_id=322 status=active deleted_at=None +-- rule_set id=25 tenant_code=PUBLIC rule_type=contract.gift.general current_version_id=323 status=active deleted_at=None +-- rule_set id=26 tenant_code=PUBLIC rule_type=contract.lease current_version_id=324 status=active deleted_at=None +-- rule_set id=27 tenant_code=PUBLIC rule_type=contract.loan.general current_version_id=325 status=active deleted_at=None +-- rule_set id=28 tenant_code=PUBLIC rule_type=contract.purchase.general current_version_id=326 status=active deleted_at=None +-- rule_set id=29 tenant_code=PUBLIC rule_type=contract.sale current_version_id=327 status=active deleted_at=None +-- rule_set id=30 tenant_code=PUBLIC rule_type=contract.tech current_version_id=328 status=active deleted_at=None +-- rule_set id=31 tenant_code=PUBLIC rule_type=行政卷宗.行政处罚 current_version_id=330 status=active deleted_at=None +-- rule_set id=32 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.停业 current_version_id=331 status=active deleted_at=None +-- rule_set id=33 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.变更 current_version_id=332 status=active deleted_at=None +-- rule_set id=34 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.延续 current_version_id=333 status=active deleted_at=None +-- rule_set id=35 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.恢复营业 current_version_id=334 status=active deleted_at=None +-- rule_set id=36 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.收回 current_version_id=335 status=active deleted_at=None +-- rule_set id=37 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.新办 current_version_id=336 status=active deleted_at=None +-- rule_set id=38 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.歇业 current_version_id=337 status=active deleted_at=None +-- rule_set id=39 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.注销 current_version_id=338 status=active deleted_at=None +-- rule_set id=40 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.补办 current_version_id=339 status=active deleted_at=None +-- rule_set id=41 tenant_code=PUBLIC rule_type=govdoc.general current_version_id=329 status=active deleted_at=None +-- rule_set id=44 tenant_code=JY rule_type=contract.entrust current_version_id=258 status=active deleted_at=None +-- rule_set id=107 tenant_code=MZ rule_type=govdoc.general current_version_id=298 status=active deleted_at=None +-- rule_set id=108 tenant_code=MZ rule_type=contract.gift.charity current_version_id=291 status=active deleted_at=None +-- rule_set id=109 tenant_code=MZ rule_type=contract.gift.general current_version_id=292 status=active deleted_at=None +-- rule_set id=110 tenant_code=MZ rule_type=contract.lease current_version_id=293 status=active deleted_at=None +-- rule_set id=111 tenant_code=MZ rule_type=contract.loan.general current_version_id=294 status=active deleted_at=None +-- rule_set id=112 tenant_code=MZ rule_type=contract.purchase.general current_version_id=295 status=active deleted_at=None +-- rule_set id=113 tenant_code=MZ rule_type=contract.sale current_version_id=296 status=active deleted_at=None +-- rule_set id=114 tenant_code=MZ rule_type=行政卷宗.行政处罚 current_version_id=299 status=active deleted_at=None +-- rule_set id=115 tenant_code=MZ rule_type=行政卷宗.行政许可.停业 current_version_id=300 status=active deleted_at=None +-- rule_set id=116 tenant_code=MZ rule_type=行政卷宗.行政许可.变更 current_version_id=301 status=active deleted_at=None +-- rule_set id=117 tenant_code=MZ rule_type=行政卷宗.行政许可.延续 current_version_id=302 status=active deleted_at=None +-- rule_set id=118 tenant_code=MZ rule_type=行政卷宗.行政许可.恢复营业 current_version_id=303 status=active deleted_at=None +-- rule_set id=119 tenant_code=MZ rule_type=行政卷宗.行政许可.收回 current_version_id=304 status=active deleted_at=None +-- rule_set id=120 tenant_code=MZ rule_type=行政卷宗.行政许可.新办 current_version_id=305 status=active deleted_at=None +-- rule_set id=121 tenant_code=MZ rule_type=行政卷宗.行政许可.歇业 current_version_id=306 status=active deleted_at=None +-- rule_set id=122 tenant_code=MZ rule_type=行政卷宗.行政许可.注销 current_version_id=307 status=active deleted_at=None +-- rule_set id=123 tenant_code=MZ rule_type=行政卷宗.行政许可.补办 current_version_id=308 status=active deleted_at=None +-- rule_set id=124 tenant_code=MZ rule_type=contract.tech current_version_id=297 status=active deleted_at=None +-- rule_set id=125 tenant_code=MZ rule_type=contract.evaluation.delegation current_version_id=290 status=active deleted_at=None +-- rule_set id=126 tenant_code=MZ rule_type=contract.construction.general current_version_id=280 status=active deleted_at=None +-- rule_set id=127 tenant_code=MZ rule_type=contract.entrust current_version_id=289 status=active deleted_at=None +-- rule_set id=128 tenant_code=YF rule_type=govdoc.general current_version_id=360 status=active deleted_at=None +-- rule_set id=129 tenant_code=YF rule_type=contract.gift.charity current_version_id=353 status=active deleted_at=None +-- rule_set id=130 tenant_code=YF rule_type=contract.gift.general current_version_id=354 status=active deleted_at=None +-- rule_set id=131 tenant_code=YF rule_type=contract.lease current_version_id=355 status=active deleted_at=None +-- rule_set id=132 tenant_code=YF rule_type=contract.loan.general current_version_id=356 status=active deleted_at=None +-- rule_set id=133 tenant_code=YF rule_type=contract.purchase.general current_version_id=357 status=active deleted_at=None +-- rule_set id=134 tenant_code=YF rule_type=contract.sale current_version_id=358 status=active deleted_at=None +-- rule_set id=135 tenant_code=YF rule_type=行政卷宗.行政处罚 current_version_id=361 status=active deleted_at=None +-- rule_set id=136 tenant_code=YF rule_type=行政卷宗.行政许可.停业 current_version_id=362 status=active deleted_at=None +-- rule_set id=137 tenant_code=YF rule_type=行政卷宗.行政许可.变更 current_version_id=363 status=active deleted_at=None +-- rule_set id=138 tenant_code=YF rule_type=行政卷宗.行政许可.延续 current_version_id=364 status=active deleted_at=None +-- rule_set id=139 tenant_code=YF rule_type=行政卷宗.行政许可.恢复营业 current_version_id=365 status=active deleted_at=None +-- rule_set id=140 tenant_code=YF rule_type=行政卷宗.行政许可.收回 current_version_id=366 status=active deleted_at=None +-- rule_set id=141 tenant_code=YF rule_type=行政卷宗.行政许可.新办 current_version_id=367 status=active deleted_at=None +-- rule_set id=142 tenant_code=YF rule_type=行政卷宗.行政许可.歇业 current_version_id=368 status=active deleted_at=None +-- rule_set id=143 tenant_code=YF rule_type=行政卷宗.行政许可.注销 current_version_id=369 status=active deleted_at=None +-- rule_set id=144 tenant_code=YF rule_type=行政卷宗.行政许可.补办 current_version_id=370 status=active deleted_at=None +-- rule_set id=145 tenant_code=YF rule_type=contract.tech current_version_id=359 status=active deleted_at=None +-- rule_set id=146 tenant_code=YF rule_type=contract.evaluation.delegation current_version_id=352 status=active deleted_at=None +-- rule_set id=147 tenant_code=YF rule_type=contract.construction.general current_version_id=342 status=active deleted_at=None +-- rule_set id=148 tenant_code=YF rule_type=contract.entrust current_version_id=351 status=active deleted_at=None +-- rule_set id=149 tenant_code=JY rule_type=govdoc.general current_version_id=267 status=active deleted_at=None +-- rule_set id=150 tenant_code=JY rule_type=contract.gift.charity current_version_id=260 status=active deleted_at=None +-- rule_set id=151 tenant_code=JY rule_type=contract.gift.general current_version_id=261 status=active deleted_at=None +-- rule_set id=152 tenant_code=JY rule_type=contract.lease current_version_id=262 status=active deleted_at=None +-- rule_set id=153 tenant_code=JY rule_type=contract.loan.general current_version_id=263 status=active deleted_at=None +-- rule_set id=154 tenant_code=JY rule_type=contract.purchase.general current_version_id=264 status=active deleted_at=None +-- rule_set id=155 tenant_code=JY rule_type=contract.sale current_version_id=265 status=active deleted_at=None +-- rule_set id=156 tenant_code=JY rule_type=行政卷宗.行政处罚 current_version_id=268 status=active deleted_at=None +-- rule_set id=157 tenant_code=JY rule_type=行政卷宗.行政许可.停业 current_version_id=269 status=active deleted_at=None +-- rule_set id=158 tenant_code=JY rule_type=行政卷宗.行政许可.变更 current_version_id=270 status=active deleted_at=None +-- rule_set id=159 tenant_code=JY rule_type=行政卷宗.行政许可.延续 current_version_id=271 status=active deleted_at=None +-- rule_set id=160 tenant_code=JY rule_type=行政卷宗.行政许可.恢复营业 current_version_id=272 status=active deleted_at=None +-- rule_set id=161 tenant_code=JY rule_type=行政卷宗.行政许可.收回 current_version_id=273 status=active deleted_at=None +-- rule_set id=162 tenant_code=JY rule_type=行政卷宗.行政许可.新办 current_version_id=274 status=active deleted_at=None +-- rule_set id=163 tenant_code=JY rule_type=行政卷宗.行政许可.歇业 current_version_id=275 status=active deleted_at=None +-- rule_set id=164 tenant_code=JY rule_type=行政卷宗.行政许可.注销 current_version_id=276 status=active deleted_at=None +-- rule_set id=165 tenant_code=JY rule_type=行政卷宗.行政许可.补办 current_version_id=277 status=active deleted_at=None +-- rule_set id=166 tenant_code=JY rule_type=contract.tech current_version_id=266 status=active deleted_at=None +-- rule_set id=167 tenant_code=JY rule_type=contract.evaluation.delegation current_version_id=259 status=active deleted_at=None +-- rule_set id=168 tenant_code=JY rule_type=contract.construction.general current_version_id=249 status=active deleted_at=None +-- rule_set id=169 tenant_code=CZ rule_type=govdoc.general current_version_id=236 status=active deleted_at=None +-- rule_set id=170 tenant_code=CZ rule_type=contract.gift.charity current_version_id=229 status=active deleted_at=None +-- rule_set id=171 tenant_code=CZ rule_type=contract.gift.general current_version_id=230 status=active deleted_at=None +-- rule_set id=172 tenant_code=CZ rule_type=contract.lease current_version_id=231 status=active deleted_at=None +-- rule_set id=173 tenant_code=CZ rule_type=contract.loan.general current_version_id=232 status=active deleted_at=None +-- rule_set id=174 tenant_code=CZ rule_type=contract.purchase.general current_version_id=233 status=active deleted_at=None +-- rule_set id=175 tenant_code=CZ rule_type=contract.sale current_version_id=234 status=active deleted_at=None +-- rule_set id=176 tenant_code=CZ rule_type=行政卷宗.行政处罚 current_version_id=237 status=active deleted_at=None +-- rule_set id=177 tenant_code=CZ rule_type=行政卷宗.行政许可.停业 current_version_id=238 status=active deleted_at=None +-- rule_set id=178 tenant_code=CZ rule_type=行政卷宗.行政许可.变更 current_version_id=239 status=active deleted_at=None +-- rule_set id=179 tenant_code=CZ rule_type=行政卷宗.行政许可.延续 current_version_id=240 status=active deleted_at=None +-- rule_set id=180 tenant_code=CZ rule_type=行政卷宗.行政许可.恢复营业 current_version_id=241 status=active deleted_at=None +-- rule_set id=181 tenant_code=CZ rule_type=行政卷宗.行政许可.收回 current_version_id=242 status=active deleted_at=None +-- rule_set id=182 tenant_code=CZ rule_type=行政卷宗.行政许可.新办 current_version_id=243 status=active deleted_at=None +-- rule_set id=183 tenant_code=CZ rule_type=行政卷宗.行政许可.歇业 current_version_id=244 status=active deleted_at=None +-- rule_set id=184 tenant_code=CZ rule_type=行政卷宗.行政许可.注销 current_version_id=245 status=active deleted_at=None +-- rule_set id=185 tenant_code=CZ rule_type=行政卷宗.行政许可.补办 current_version_id=246 status=active deleted_at=None +-- rule_set id=186 tenant_code=CZ rule_type=contract.tech current_version_id=235 status=active deleted_at=None +-- rule_set id=187 tenant_code=CZ rule_type=contract.evaluation.delegation current_version_id=228 status=active deleted_at=None +-- rule_set id=188 tenant_code=CZ rule_type=contract.construction.general current_version_id=218 status=active deleted_at=None +-- rule_set id=189 tenant_code=CZ rule_type=contract.entrust current_version_id=227 status=active deleted_at=None +-- rule_set id=190 tenant_code=PTA01 rule_type=contract.gift.charity current_version_id=371 status=active deleted_at=None +-- rule_set id=191 tenant_code=PTA01 rule_type=govdoc.general current_version_id=372 status=active deleted_at=None +-- rule_set id=192 tenant_code=PTA01 rule_type=contract.construction.general current_version_id=375 status=active deleted_at=None +-- rule_set id=193 tenant_code=PTA01 rule_type=contract.entrust current_version_id=384 status=active deleted_at=None +-- rule_set id=194 tenant_code=PTA01 rule_type=contract.evaluation.delegation current_version_id=385 status=active deleted_at=None +-- rule_set id=195 tenant_code=PTA01 rule_type=contract.gift.general current_version_id=386 status=active deleted_at=None +-- rule_set id=196 tenant_code=PTA01 rule_type=contract.lease current_version_id=387 status=active deleted_at=None +-- rule_set id=197 tenant_code=PTA01 rule_type=contract.loan.general current_version_id=388 status=active deleted_at=None +-- rule_set id=198 tenant_code=PTA01 rule_type=contract.purchase.general current_version_id=389 status=active deleted_at=None +-- rule_set id=199 tenant_code=PTA01 rule_type=contract.sale current_version_id=390 status=active deleted_at=None +-- rule_set id=200 tenant_code=PTA01 rule_type=contract.tech current_version_id=391 status=active deleted_at=None +-- rule_set id=201 tenant_code=PTA01 rule_type=行政卷宗.行政处罚 current_version_id=392 status=active deleted_at=None +-- rule_set id=202 tenant_code=PTA01 rule_type=行政卷宗.行政许可.停业 current_version_id=393 status=active deleted_at=None +-- rule_set id=203 tenant_code=PTA01 rule_type=行政卷宗.行政许可.变更 current_version_id=394 status=active deleted_at=None +-- rule_set id=204 tenant_code=PTA01 rule_type=行政卷宗.行政许可.延续 current_version_id=395 status=active deleted_at=None +-- rule_set id=205 tenant_code=PTA01 rule_type=行政卷宗.行政许可.恢复营业 current_version_id=396 status=active deleted_at=None +-- rule_set id=206 tenant_code=PTA01 rule_type=行政卷宗.行政许可.收回 current_version_id=397 status=active deleted_at=None +-- rule_set id=207 tenant_code=PTA01 rule_type=行政卷宗.行政许可.新办 current_version_id=398 status=active deleted_at=None +-- rule_set id=208 tenant_code=PTA01 rule_type=行政卷宗.行政许可.歇业 current_version_id=399 status=active deleted_at=None +-- rule_set id=209 tenant_code=PTA01 rule_type=行政卷宗.行政许可.注销 current_version_id=400 status=active deleted_at=None +-- rule_set id=210 tenant_code=PTA01 rule_type=行政卷宗.行政许可.补办 current_version_id=401 status=active deleted_at=None +-- rule_set id=211 tenant_code=PTB01 rule_type=contract.gift.charity current_version_id=402 status=active deleted_at=None +-- rule_set id=212 tenant_code=PTB01 rule_type=govdoc.general current_version_id=403 status=active deleted_at=None +-- rule_set id=213 tenant_code=PTB01 rule_type=contract.construction.general current_version_id=406 status=active deleted_at=None +-- rule_set id=214 tenant_code=PTB01 rule_type=contract.entrust current_version_id=415 status=active deleted_at=None +-- rule_set id=215 tenant_code=PTB01 rule_type=contract.evaluation.delegation current_version_id=416 status=active deleted_at=None +-- rule_set id=216 tenant_code=PTB01 rule_type=contract.gift.general current_version_id=417 status=active deleted_at=None +-- rule_set id=217 tenant_code=PTB01 rule_type=contract.lease current_version_id=418 status=active deleted_at=None +-- rule_set id=218 tenant_code=PTB01 rule_type=contract.loan.general current_version_id=419 status=active deleted_at=None +-- rule_set id=219 tenant_code=PTB01 rule_type=contract.purchase.general current_version_id=420 status=active deleted_at=None +-- rule_set id=220 tenant_code=PTB01 rule_type=contract.sale current_version_id=421 status=active deleted_at=None +-- rule_set id=221 tenant_code=PTB01 rule_type=contract.tech current_version_id=422 status=active deleted_at=None +-- rule_set id=222 tenant_code=PTB01 rule_type=行政卷宗.行政处罚 current_version_id=423 status=active deleted_at=None +-- rule_set id=223 tenant_code=PTB01 rule_type=行政卷宗.行政许可.停业 current_version_id=424 status=active deleted_at=None +-- rule_set id=224 tenant_code=PTB01 rule_type=行政卷宗.行政许可.变更 current_version_id=425 status=active deleted_at=None +-- rule_set id=225 tenant_code=PTB01 rule_type=行政卷宗.行政许可.延续 current_version_id=426 status=active deleted_at=None +-- rule_set id=226 tenant_code=PTB01 rule_type=行政卷宗.行政许可.恢复营业 current_version_id=427 status=active deleted_at=None +-- rule_set id=227 tenant_code=PTB01 rule_type=行政卷宗.行政许可.收回 current_version_id=428 status=active deleted_at=None +-- rule_set id=228 tenant_code=PTB01 rule_type=行政卷宗.行政许可.新办 current_version_id=429 status=active deleted_at=None +-- rule_set id=229 tenant_code=PTB01 rule_type=行政卷宗.行政许可.歇业 current_version_id=430 status=active deleted_at=None +-- rule_set id=230 tenant_code=PTB01 rule_type=行政卷宗.行政许可.注销 current_version_id=431 status=active deleted_at=None +-- rule_set id=231 tenant_code=PTB01 rule_type=行政卷宗.行政许可.补办 current_version_id=432 status=active deleted_at=None + +-- rule_version id=1 rule_set_id=21 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=2 rule_set_id=22 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=3 rule_set_id=23 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=4 rule_set_id=24 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=5 rule_set_id=25 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=6 rule_set_id=26 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=7 rule_set_id=27 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=8 rule_set_id=28 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=9 rule_set_id=29 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=10 rule_set_id=30 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=11 rule_set_id=31 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=12 rule_set_id=32 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=13 rule_set_id=33 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=14 rule_set_id=34 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=15 rule_set_id=35 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=16 rule_set_id=36 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=17 rule_set_id=37 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=18 rule_set_id=38 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=19 rule_set_id=39 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=20 rule_set_id=40 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=21 rule_set_id=21 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=22 rule_set_id=22 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=23 rule_set_id=22 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=24 rule_set_id=22 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=25 rule_set_id=22 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=26 rule_set_id=22 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=27 rule_set_id=22 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=28 rule_set_id=22 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=29 rule_set_id=22 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=30 rule_set_id=21 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=31 rule_set_id=41 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=32 rule_set_id=44 version_no=v10 status=deprecated oss_url=rules/contract.entrust/v10/rules.yaml sha=92310866a9ee3030e3b4198623ab4dc45ac5dfdd0b2cb08d334622544eb6e599 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=97 rule_set_id=107 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=98 rule_set_id=126 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=99 rule_set_id=126 version_no=v2 status=rollback oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=100 rule_set_id=126 version_no=v3 status=deprecated oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=101 rule_set_id=108 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=102 rule_set_id=109 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=103 rule_set_id=110 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=104 rule_set_id=111 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=105 rule_set_id=112 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=106 rule_set_id=113 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=107 rule_set_id=114 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=108 rule_set_id=115 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=109 rule_set_id=116 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=110 rule_set_id=117 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=111 rule_set_id=118 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=112 rule_set_id=119 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=113 rule_set_id=120 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=114 rule_set_id=121 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=115 rule_set_id=122 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=116 rule_set_id=123 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=117 rule_set_id=124 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=118 rule_set_id=125 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=119 rule_set_id=127 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=120 rule_set_id=127 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=121 rule_set_id=127 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=122 rule_set_id=127 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=123 rule_set_id=127 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=124 rule_set_id=127 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=125 rule_set_id=127 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=126 rule_set_id=127 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=127 rule_set_id=127 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=128 rule_set_id=128 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=129 rule_set_id=129 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=130 rule_set_id=130 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=131 rule_set_id=131 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=132 rule_set_id=132 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=133 rule_set_id=133 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=134 rule_set_id=134 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=135 rule_set_id=135 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=136 rule_set_id=136 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=137 rule_set_id=137 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=138 rule_set_id=138 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=139 rule_set_id=139 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=140 rule_set_id=140 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=141 rule_set_id=141 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=142 rule_set_id=142 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=143 rule_set_id=143 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=144 rule_set_id=144 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=145 rule_set_id=145 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=146 rule_set_id=146 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=147 rule_set_id=147 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=148 rule_set_id=147 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=149 rule_set_id=147 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=150 rule_set_id=148 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=151 rule_set_id=148 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=152 rule_set_id=148 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=153 rule_set_id=148 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=154 rule_set_id=148 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=155 rule_set_id=148 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=156 rule_set_id=148 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=157 rule_set_id=148 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=158 rule_set_id=148 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=159 rule_set_id=149 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=160 rule_set_id=150 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=161 rule_set_id=151 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=162 rule_set_id=152 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=163 rule_set_id=153 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=164 rule_set_id=154 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=165 rule_set_id=155 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=166 rule_set_id=156 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=167 rule_set_id=157 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=168 rule_set_id=158 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=169 rule_set_id=159 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=170 rule_set_id=160 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=171 rule_set_id=161 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=172 rule_set_id=162 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=173 rule_set_id=163 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=174 rule_set_id=164 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=175 rule_set_id=165 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=176 rule_set_id=166 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=177 rule_set_id=167 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=178 rule_set_id=168 version_no=1.2 status=deprecated oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=179 rule_set_id=168 version_no=v2 status=rollback oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=180 rule_set_id=168 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=181 rule_set_id=169 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=182 rule_set_id=170 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=183 rule_set_id=171 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=184 rule_set_id=172 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=185 rule_set_id=173 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=186 rule_set_id=174 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=187 rule_set_id=175 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=188 rule_set_id=176 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=189 rule_set_id=177 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=190 rule_set_id=178 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=191 rule_set_id=179 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=192 rule_set_id=180 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=193 rule_set_id=181 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=194 rule_set_id=182 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=195 rule_set_id=183 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=196 rule_set_id=184 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=197 rule_set_id=185 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=198 rule_set_id=186 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=199 rule_set_id=187 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=200 rule_set_id=188 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=201 rule_set_id=188 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=202 rule_set_id=188 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=203 rule_set_id=189 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=204 rule_set_id=189 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=205 rule_set_id=189 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=206 rule_set_id=189 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=207 rule_set_id=189 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=208 rule_set_id=189 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=209 rule_set_id=189 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=210 rule_set_id=189 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=211 rule_set_id=189 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=212 rule_set_id=168 version_no=v4 status=rollback oss_url=rules/contract.construction.general/v4/rules.yaml sha=5b058dbb0dd14a31132110f04e649d26cc2d9f544ec2f8ffa56c4ada1917cd13 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=213 rule_set_id=22 version_no=v10 status=draft oss_url=rules/contract.entrust/v10/rules.yaml sha=0481fb582bf30fb137d9552cecdae22fd6ee525954b893ccaec386b186caabcc deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=214 rule_set_id=22 version_no=v11 status=draft oss_url=rules/contract.entrust/v11/rules.yaml sha=4fb270e13c9c3ab9d771807f9f333232a9cf78567163521606165b0889200c3e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=215 rule_set_id=127 version_no=pytest-vm-1779365463 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779365463/rules.yaml sha=59763ad2915c90871dfa641264b74fe22f164b7590bd26a71f448dccba66d4e0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=216 rule_set_id=188 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=217 rule_set_id=188 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=218 rule_set_id=188 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=219 rule_set_id=189 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=220 rule_set_id=189 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=221 rule_set_id=189 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=222 rule_set_id=189 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=223 rule_set_id=189 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=224 rule_set_id=189 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=225 rule_set_id=189 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=226 rule_set_id=189 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=227 rule_set_id=189 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=228 rule_set_id=187 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=229 rule_set_id=170 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=230 rule_set_id=171 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=231 rule_set_id=172 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=232 rule_set_id=173 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=233 rule_set_id=174 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=234 rule_set_id=175 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=235 rule_set_id=186 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=236 rule_set_id=169 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=237 rule_set_id=176 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=238 rule_set_id=177 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=239 rule_set_id=178 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=240 rule_set_id=179 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=241 rule_set_id=180 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=242 rule_set_id=181 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=243 rule_set_id=182 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=244 rule_set_id=183 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=245 rule_set_id=184 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=246 rule_set_id=185 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=247 rule_set_id=168 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=248 rule_set_id=168 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=249 rule_set_id=168 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=250 rule_set_id=44 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=251 rule_set_id=44 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=252 rule_set_id=44 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=253 rule_set_id=44 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=254 rule_set_id=44 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=255 rule_set_id=44 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=256 rule_set_id=44 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=257 rule_set_id=44 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=258 rule_set_id=44 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=259 rule_set_id=167 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=260 rule_set_id=150 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=261 rule_set_id=151 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=262 rule_set_id=152 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=263 rule_set_id=153 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=264 rule_set_id=154 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=265 rule_set_id=155 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=266 rule_set_id=166 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=267 rule_set_id=149 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=268 rule_set_id=156 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=269 rule_set_id=157 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=270 rule_set_id=158 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=271 rule_set_id=159 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=272 rule_set_id=160 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=273 rule_set_id=161 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=274 rule_set_id=162 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=275 rule_set_id=163 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=276 rule_set_id=164 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=277 rule_set_id=165 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=278 rule_set_id=126 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=279 rule_set_id=126 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=280 rule_set_id=126 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=281 rule_set_id=127 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=282 rule_set_id=127 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=283 rule_set_id=127 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=284 rule_set_id=127 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=285 rule_set_id=127 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=286 rule_set_id=127 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=287 rule_set_id=127 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=288 rule_set_id=127 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=289 rule_set_id=127 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=290 rule_set_id=125 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=291 rule_set_id=108 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=292 rule_set_id=109 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=293 rule_set_id=110 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=294 rule_set_id=111 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=295 rule_set_id=112 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=296 rule_set_id=113 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=297 rule_set_id=124 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=298 rule_set_id=107 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=299 rule_set_id=114 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=300 rule_set_id=115 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=301 rule_set_id=116 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=302 rule_set_id=117 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=303 rule_set_id=118 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=304 rule_set_id=119 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=305 rule_set_id=120 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=306 rule_set_id=121 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=307 rule_set_id=122 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=308 rule_set_id=123 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=309 rule_set_id=21 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=310 rule_set_id=21 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=311 rule_set_id=21 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=312 rule_set_id=22 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=313 rule_set_id=22 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=314 rule_set_id=22 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=315 rule_set_id=22 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=316 rule_set_id=22 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=317 rule_set_id=22 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=318 rule_set_id=22 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=319 rule_set_id=22 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=320 rule_set_id=22 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=321 rule_set_id=23 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=322 rule_set_id=24 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=323 rule_set_id=25 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=324 rule_set_id=26 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=325 rule_set_id=27 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=326 rule_set_id=28 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=327 rule_set_id=29 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=328 rule_set_id=30 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=329 rule_set_id=41 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=330 rule_set_id=31 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=331 rule_set_id=32 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=332 rule_set_id=33 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=333 rule_set_id=34 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=334 rule_set_id=35 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=335 rule_set_id=36 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=336 rule_set_id=37 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=337 rule_set_id=38 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=338 rule_set_id=39 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=339 rule_set_id=40 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=340 rule_set_id=147 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=341 rule_set_id=147 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=342 rule_set_id=147 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=343 rule_set_id=148 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=344 rule_set_id=148 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=345 rule_set_id=148 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=346 rule_set_id=148 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=347 rule_set_id=148 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=348 rule_set_id=148 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=349 rule_set_id=148 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=350 rule_set_id=148 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=351 rule_set_id=148 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=352 rule_set_id=146 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=353 rule_set_id=129 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=354 rule_set_id=130 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=355 rule_set_id=131 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=356 rule_set_id=132 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=357 rule_set_id=133 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=358 rule_set_id=134 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=359 rule_set_id=145 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=360 rule_set_id=128 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=361 rule_set_id=135 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=362 rule_set_id=136 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=363 rule_set_id=137 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=364 rule_set_id=138 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=365 rule_set_id=139 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=366 rule_set_id=140 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=367 rule_set_id=141 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=368 rule_set_id=142 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=369 rule_set_id=143 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=370 rule_set_id=144 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=371 rule_set_id=190 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=372 rule_set_id=191 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=373 rule_set_id=192 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=374 rule_set_id=192 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=375 rule_set_id=192 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=376 rule_set_id=193 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=377 rule_set_id=193 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=378 rule_set_id=193 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=379 rule_set_id=193 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=380 rule_set_id=193 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=381 rule_set_id=193 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=382 rule_set_id=193 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=383 rule_set_id=193 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=384 rule_set_id=193 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=385 rule_set_id=194 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=386 rule_set_id=195 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=387 rule_set_id=196 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=388 rule_set_id=197 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=389 rule_set_id=198 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=390 rule_set_id=199 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=391 rule_set_id=200 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=392 rule_set_id=201 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=393 rule_set_id=202 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=394 rule_set_id=203 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=395 rule_set_id=204 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=396 rule_set_id=205 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=397 rule_set_id=206 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=398 rule_set_id=207 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=399 rule_set_id=208 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=400 rule_set_id=209 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=401 rule_set_id=210 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=402 rule_set_id=211 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=403 rule_set_id=212 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=404 rule_set_id=213 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=405 rule_set_id=213 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=406 rule_set_id=213 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=407 rule_set_id=214 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=408 rule_set_id=214 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=409 rule_set_id=214 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=410 rule_set_id=214 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=411 rule_set_id=214 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=412 rule_set_id=214 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=413 rule_set_id=214 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=414 rule_set_id=214 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=415 rule_set_id=214 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=416 rule_set_id=215 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=417 rule_set_id=216 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=418 rule_set_id=217 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=419 rule_set_id=218 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=420 rule_set_id=219 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=421 rule_set_id=220 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=422 rule_set_id=221 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=423 rule_set_id=222 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=424 rule_set_id=223 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=425 rule_set_id=224 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=426 rule_set_id=225 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=427 rule_set_id=226 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=428 rule_set_id=227 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=429 rule_set_id=228 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=430 rule_set_id=229 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=431 rule_set_id=230 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=432 rule_set_id=231 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=433 rule_set_id=127 version_no=pytest-vm-1779371496 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779371496/rules.yaml sha=6bb8ef6ffec27b920c9f713243e85fd19f858c3cb1b6a3216819a5c167a7bfaf deleted_at=None +-- rule_version id=434 rule_set_id=127 version_no=pytest-vm-1779371996 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779371996/rules.yaml sha=4ba3e8f648ffd28d18a97d52c1c826d2ea6a6ef582c15e4e1f2bc1f1fb31e2e5 deleted_at=None +-- rule_version id=435 rule_set_id=127 version_no=pytest-vm-1779372327 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779372327/rules.yaml sha=82efcd120f121d7ba6f9c6c3b310d3431ff69372e328de30c3ec73ad77b8d0cf deleted_at=None diff --git a/docs/规则编辑/backups/rule-domain-before-reset-20260521-221940.sql b/docs/规则编辑/backups/rule-domain-before-reset-20260521-221940.sql new file mode 100644 index 0000000..5f82b50 --- /dev/null +++ b/docs/规则编辑/backups/rule-domain-before-reset-20260521-221940.sql @@ -0,0 +1,527 @@ +-- Rule domain backup before reset +-- generated_at: 2026-05-21T22:19:40 +-- rule_sets: 147 +-- rule_versions: 371 + +-- This file is an audit snapshot, not an automatic restore script. +-- Use the rows below to inspect pre-reset IDs, current_version_id, oss_url and sha. + +-- rule_set id=21 tenant_code=PUBLIC rule_type=contract.construction.general current_version_id=311 status=active deleted_at=None +-- rule_set id=22 tenant_code=PUBLIC rule_type=contract.entrust current_version_id=320 status=active deleted_at=None +-- rule_set id=23 tenant_code=PUBLIC rule_type=contract.evaluation.delegation current_version_id=321 status=active deleted_at=None +-- rule_set id=24 tenant_code=PUBLIC rule_type=contract.gift.charity current_version_id=322 status=active deleted_at=None +-- rule_set id=25 tenant_code=PUBLIC rule_type=contract.gift.general current_version_id=323 status=active deleted_at=None +-- rule_set id=26 tenant_code=PUBLIC rule_type=contract.lease current_version_id=324 status=active deleted_at=None +-- rule_set id=27 tenant_code=PUBLIC rule_type=contract.loan.general current_version_id=325 status=active deleted_at=None +-- rule_set id=28 tenant_code=PUBLIC rule_type=contract.purchase.general current_version_id=326 status=active deleted_at=None +-- rule_set id=29 tenant_code=PUBLIC rule_type=contract.sale current_version_id=327 status=active deleted_at=None +-- rule_set id=30 tenant_code=PUBLIC rule_type=contract.tech current_version_id=328 status=active deleted_at=None +-- rule_set id=31 tenant_code=PUBLIC rule_type=行政卷宗.行政处罚 current_version_id=330 status=active deleted_at=None +-- rule_set id=32 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.停业 current_version_id=331 status=active deleted_at=None +-- rule_set id=33 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.变更 current_version_id=332 status=active deleted_at=None +-- rule_set id=34 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.延续 current_version_id=333 status=active deleted_at=None +-- rule_set id=35 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.恢复营业 current_version_id=334 status=active deleted_at=None +-- rule_set id=36 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.收回 current_version_id=335 status=active deleted_at=None +-- rule_set id=37 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.新办 current_version_id=336 status=active deleted_at=None +-- rule_set id=38 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.歇业 current_version_id=337 status=active deleted_at=None +-- rule_set id=39 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.注销 current_version_id=338 status=active deleted_at=None +-- rule_set id=40 tenant_code=PUBLIC rule_type=行政卷宗.行政许可.补办 current_version_id=339 status=active deleted_at=None +-- rule_set id=41 tenant_code=PUBLIC rule_type=govdoc.general current_version_id=329 status=active deleted_at=None +-- rule_set id=44 tenant_code=JY rule_type=contract.entrust current_version_id=258 status=active deleted_at=None +-- rule_set id=107 tenant_code=MZ rule_type=govdoc.general current_version_id=298 status=active deleted_at=None +-- rule_set id=108 tenant_code=MZ rule_type=contract.gift.charity current_version_id=291 status=active deleted_at=None +-- rule_set id=109 tenant_code=MZ rule_type=contract.gift.general current_version_id=292 status=active deleted_at=None +-- rule_set id=110 tenant_code=MZ rule_type=contract.lease current_version_id=293 status=active deleted_at=None +-- rule_set id=111 tenant_code=MZ rule_type=contract.loan.general current_version_id=294 status=active deleted_at=None +-- rule_set id=112 tenant_code=MZ rule_type=contract.purchase.general current_version_id=295 status=active deleted_at=None +-- rule_set id=113 tenant_code=MZ rule_type=contract.sale current_version_id=296 status=active deleted_at=None +-- rule_set id=114 tenant_code=MZ rule_type=行政卷宗.行政处罚 current_version_id=299 status=active deleted_at=None +-- rule_set id=115 tenant_code=MZ rule_type=行政卷宗.行政许可.停业 current_version_id=300 status=active deleted_at=None +-- rule_set id=116 tenant_code=MZ rule_type=行政卷宗.行政许可.变更 current_version_id=301 status=active deleted_at=None +-- rule_set id=117 tenant_code=MZ rule_type=行政卷宗.行政许可.延续 current_version_id=302 status=active deleted_at=None +-- rule_set id=118 tenant_code=MZ rule_type=行政卷宗.行政许可.恢复营业 current_version_id=303 status=active deleted_at=None +-- rule_set id=119 tenant_code=MZ rule_type=行政卷宗.行政许可.收回 current_version_id=304 status=active deleted_at=None +-- rule_set id=120 tenant_code=MZ rule_type=行政卷宗.行政许可.新办 current_version_id=305 status=active deleted_at=None +-- rule_set id=121 tenant_code=MZ rule_type=行政卷宗.行政许可.歇业 current_version_id=306 status=active deleted_at=None +-- rule_set id=122 tenant_code=MZ rule_type=行政卷宗.行政许可.注销 current_version_id=307 status=active deleted_at=None +-- rule_set id=123 tenant_code=MZ rule_type=行政卷宗.行政许可.补办 current_version_id=308 status=active deleted_at=None +-- rule_set id=124 tenant_code=MZ rule_type=contract.tech current_version_id=297 status=active deleted_at=None +-- rule_set id=125 tenant_code=MZ rule_type=contract.evaluation.delegation current_version_id=290 status=active deleted_at=None +-- rule_set id=126 tenant_code=MZ rule_type=contract.construction.general current_version_id=280 status=active deleted_at=None +-- rule_set id=127 tenant_code=MZ rule_type=contract.entrust current_version_id=289 status=active deleted_at=None +-- rule_set id=128 tenant_code=YF rule_type=govdoc.general current_version_id=360 status=active deleted_at=None +-- rule_set id=129 tenant_code=YF rule_type=contract.gift.charity current_version_id=353 status=active deleted_at=None +-- rule_set id=130 tenant_code=YF rule_type=contract.gift.general current_version_id=354 status=active deleted_at=None +-- rule_set id=131 tenant_code=YF rule_type=contract.lease current_version_id=355 status=active deleted_at=None +-- rule_set id=132 tenant_code=YF rule_type=contract.loan.general current_version_id=356 status=active deleted_at=None +-- rule_set id=133 tenant_code=YF rule_type=contract.purchase.general current_version_id=357 status=active deleted_at=None +-- rule_set id=134 tenant_code=YF rule_type=contract.sale current_version_id=358 status=active deleted_at=None +-- rule_set id=135 tenant_code=YF rule_type=行政卷宗.行政处罚 current_version_id=361 status=active deleted_at=None +-- rule_set id=136 tenant_code=YF rule_type=行政卷宗.行政许可.停业 current_version_id=362 status=active deleted_at=None +-- rule_set id=137 tenant_code=YF rule_type=行政卷宗.行政许可.变更 current_version_id=363 status=active deleted_at=None +-- rule_set id=138 tenant_code=YF rule_type=行政卷宗.行政许可.延续 current_version_id=364 status=active deleted_at=None +-- rule_set id=139 tenant_code=YF rule_type=行政卷宗.行政许可.恢复营业 current_version_id=365 status=active deleted_at=None +-- rule_set id=140 tenant_code=YF rule_type=行政卷宗.行政许可.收回 current_version_id=366 status=active deleted_at=None +-- rule_set id=141 tenant_code=YF rule_type=行政卷宗.行政许可.新办 current_version_id=367 status=active deleted_at=None +-- rule_set id=142 tenant_code=YF rule_type=行政卷宗.行政许可.歇业 current_version_id=368 status=active deleted_at=None +-- rule_set id=143 tenant_code=YF rule_type=行政卷宗.行政许可.注销 current_version_id=369 status=active deleted_at=None +-- rule_set id=144 tenant_code=YF rule_type=行政卷宗.行政许可.补办 current_version_id=370 status=active deleted_at=None +-- rule_set id=145 tenant_code=YF rule_type=contract.tech current_version_id=359 status=active deleted_at=None +-- rule_set id=146 tenant_code=YF rule_type=contract.evaluation.delegation current_version_id=352 status=active deleted_at=None +-- rule_set id=147 tenant_code=YF rule_type=contract.construction.general current_version_id=342 status=active deleted_at=None +-- rule_set id=148 tenant_code=YF rule_type=contract.entrust current_version_id=351 status=active deleted_at=None +-- rule_set id=149 tenant_code=JY rule_type=govdoc.general current_version_id=267 status=active deleted_at=None +-- rule_set id=150 tenant_code=JY rule_type=contract.gift.charity current_version_id=260 status=active deleted_at=None +-- rule_set id=151 tenant_code=JY rule_type=contract.gift.general current_version_id=261 status=active deleted_at=None +-- rule_set id=152 tenant_code=JY rule_type=contract.lease current_version_id=262 status=active deleted_at=None +-- rule_set id=153 tenant_code=JY rule_type=contract.loan.general current_version_id=263 status=active deleted_at=None +-- rule_set id=154 tenant_code=JY rule_type=contract.purchase.general current_version_id=264 status=active deleted_at=None +-- rule_set id=155 tenant_code=JY rule_type=contract.sale current_version_id=265 status=active deleted_at=None +-- rule_set id=156 tenant_code=JY rule_type=行政卷宗.行政处罚 current_version_id=268 status=active deleted_at=None +-- rule_set id=157 tenant_code=JY rule_type=行政卷宗.行政许可.停业 current_version_id=269 status=active deleted_at=None +-- rule_set id=158 tenant_code=JY rule_type=行政卷宗.行政许可.变更 current_version_id=270 status=active deleted_at=None +-- rule_set id=159 tenant_code=JY rule_type=行政卷宗.行政许可.延续 current_version_id=271 status=active deleted_at=None +-- rule_set id=160 tenant_code=JY rule_type=行政卷宗.行政许可.恢复营业 current_version_id=272 status=active deleted_at=None +-- rule_set id=161 tenant_code=JY rule_type=行政卷宗.行政许可.收回 current_version_id=273 status=active deleted_at=None +-- rule_set id=162 tenant_code=JY rule_type=行政卷宗.行政许可.新办 current_version_id=274 status=active deleted_at=None +-- rule_set id=163 tenant_code=JY rule_type=行政卷宗.行政许可.歇业 current_version_id=275 status=active deleted_at=None +-- rule_set id=164 tenant_code=JY rule_type=行政卷宗.行政许可.注销 current_version_id=276 status=active deleted_at=None +-- rule_set id=165 tenant_code=JY rule_type=行政卷宗.行政许可.补办 current_version_id=277 status=active deleted_at=None +-- rule_set id=166 tenant_code=JY rule_type=contract.tech current_version_id=266 status=active deleted_at=None +-- rule_set id=167 tenant_code=JY rule_type=contract.evaluation.delegation current_version_id=259 status=active deleted_at=None +-- rule_set id=168 tenant_code=JY rule_type=contract.construction.general current_version_id=249 status=active deleted_at=None +-- rule_set id=169 tenant_code=CZ rule_type=govdoc.general current_version_id=236 status=active deleted_at=None +-- rule_set id=170 tenant_code=CZ rule_type=contract.gift.charity current_version_id=229 status=active deleted_at=None +-- rule_set id=171 tenant_code=CZ rule_type=contract.gift.general current_version_id=230 status=active deleted_at=None +-- rule_set id=172 tenant_code=CZ rule_type=contract.lease current_version_id=231 status=active deleted_at=None +-- rule_set id=173 tenant_code=CZ rule_type=contract.loan.general current_version_id=232 status=active deleted_at=None +-- rule_set id=174 tenant_code=CZ rule_type=contract.purchase.general current_version_id=233 status=active deleted_at=None +-- rule_set id=175 tenant_code=CZ rule_type=contract.sale current_version_id=234 status=active deleted_at=None +-- rule_set id=176 tenant_code=CZ rule_type=行政卷宗.行政处罚 current_version_id=237 status=active deleted_at=None +-- rule_set id=177 tenant_code=CZ rule_type=行政卷宗.行政许可.停业 current_version_id=238 status=active deleted_at=None +-- rule_set id=178 tenant_code=CZ rule_type=行政卷宗.行政许可.变更 current_version_id=239 status=active deleted_at=None +-- rule_set id=179 tenant_code=CZ rule_type=行政卷宗.行政许可.延续 current_version_id=240 status=active deleted_at=None +-- rule_set id=180 tenant_code=CZ rule_type=行政卷宗.行政许可.恢复营业 current_version_id=241 status=active deleted_at=None +-- rule_set id=181 tenant_code=CZ rule_type=行政卷宗.行政许可.收回 current_version_id=242 status=active deleted_at=None +-- rule_set id=182 tenant_code=CZ rule_type=行政卷宗.行政许可.新办 current_version_id=243 status=active deleted_at=None +-- rule_set id=183 tenant_code=CZ rule_type=行政卷宗.行政许可.歇业 current_version_id=244 status=active deleted_at=None +-- rule_set id=184 tenant_code=CZ rule_type=行政卷宗.行政许可.注销 current_version_id=245 status=active deleted_at=None +-- rule_set id=185 tenant_code=CZ rule_type=行政卷宗.行政许可.补办 current_version_id=246 status=active deleted_at=None +-- rule_set id=186 tenant_code=CZ rule_type=contract.tech current_version_id=235 status=active deleted_at=None +-- rule_set id=187 tenant_code=CZ rule_type=contract.evaluation.delegation current_version_id=228 status=active deleted_at=None +-- rule_set id=188 tenant_code=CZ rule_type=contract.construction.general current_version_id=218 status=active deleted_at=None +-- rule_set id=189 tenant_code=CZ rule_type=contract.entrust current_version_id=227 status=active deleted_at=None +-- rule_set id=190 tenant_code=PTA01 rule_type=contract.gift.charity current_version_id=371 status=active deleted_at=None +-- rule_set id=191 tenant_code=PTA01 rule_type=govdoc.general current_version_id=372 status=active deleted_at=None +-- rule_set id=192 tenant_code=PTA01 rule_type=contract.construction.general current_version_id=375 status=active deleted_at=None +-- rule_set id=193 tenant_code=PTA01 rule_type=contract.entrust current_version_id=384 status=active deleted_at=None +-- rule_set id=194 tenant_code=PTA01 rule_type=contract.evaluation.delegation current_version_id=385 status=active deleted_at=None +-- rule_set id=195 tenant_code=PTA01 rule_type=contract.gift.general current_version_id=386 status=active deleted_at=None +-- rule_set id=196 tenant_code=PTA01 rule_type=contract.lease current_version_id=387 status=active deleted_at=None +-- rule_set id=197 tenant_code=PTA01 rule_type=contract.loan.general current_version_id=388 status=active deleted_at=None +-- rule_set id=198 tenant_code=PTA01 rule_type=contract.purchase.general current_version_id=389 status=active deleted_at=None +-- rule_set id=199 tenant_code=PTA01 rule_type=contract.sale current_version_id=390 status=active deleted_at=None +-- rule_set id=200 tenant_code=PTA01 rule_type=contract.tech current_version_id=391 status=active deleted_at=None +-- rule_set id=201 tenant_code=PTA01 rule_type=行政卷宗.行政处罚 current_version_id=392 status=active deleted_at=None +-- rule_set id=202 tenant_code=PTA01 rule_type=行政卷宗.行政许可.停业 current_version_id=393 status=active deleted_at=None +-- rule_set id=203 tenant_code=PTA01 rule_type=行政卷宗.行政许可.变更 current_version_id=394 status=active deleted_at=None +-- rule_set id=204 tenant_code=PTA01 rule_type=行政卷宗.行政许可.延续 current_version_id=395 status=active deleted_at=None +-- rule_set id=205 tenant_code=PTA01 rule_type=行政卷宗.行政许可.恢复营业 current_version_id=396 status=active deleted_at=None +-- rule_set id=206 tenant_code=PTA01 rule_type=行政卷宗.行政许可.收回 current_version_id=397 status=active deleted_at=None +-- rule_set id=207 tenant_code=PTA01 rule_type=行政卷宗.行政许可.新办 current_version_id=398 status=active deleted_at=None +-- rule_set id=208 tenant_code=PTA01 rule_type=行政卷宗.行政许可.歇业 current_version_id=399 status=active deleted_at=None +-- rule_set id=209 tenant_code=PTA01 rule_type=行政卷宗.行政许可.注销 current_version_id=400 status=active deleted_at=None +-- rule_set id=210 tenant_code=PTA01 rule_type=行政卷宗.行政许可.补办 current_version_id=401 status=active deleted_at=None +-- rule_set id=211 tenant_code=PTB01 rule_type=contract.gift.charity current_version_id=402 status=active deleted_at=None +-- rule_set id=212 tenant_code=PTB01 rule_type=govdoc.general current_version_id=403 status=active deleted_at=None +-- rule_set id=213 tenant_code=PTB01 rule_type=contract.construction.general current_version_id=406 status=active deleted_at=None +-- rule_set id=214 tenant_code=PTB01 rule_type=contract.entrust current_version_id=415 status=active deleted_at=None +-- rule_set id=215 tenant_code=PTB01 rule_type=contract.evaluation.delegation current_version_id=416 status=active deleted_at=None +-- rule_set id=216 tenant_code=PTB01 rule_type=contract.gift.general current_version_id=417 status=active deleted_at=None +-- rule_set id=217 tenant_code=PTB01 rule_type=contract.lease current_version_id=418 status=active deleted_at=None +-- rule_set id=218 tenant_code=PTB01 rule_type=contract.loan.general current_version_id=419 status=active deleted_at=None +-- rule_set id=219 tenant_code=PTB01 rule_type=contract.purchase.general current_version_id=420 status=active deleted_at=None +-- rule_set id=220 tenant_code=PTB01 rule_type=contract.sale current_version_id=421 status=active deleted_at=None +-- rule_set id=221 tenant_code=PTB01 rule_type=contract.tech current_version_id=422 status=active deleted_at=None +-- rule_set id=222 tenant_code=PTB01 rule_type=行政卷宗.行政处罚 current_version_id=423 status=active deleted_at=None +-- rule_set id=223 tenant_code=PTB01 rule_type=行政卷宗.行政许可.停业 current_version_id=424 status=active deleted_at=None +-- rule_set id=224 tenant_code=PTB01 rule_type=行政卷宗.行政许可.变更 current_version_id=425 status=active deleted_at=None +-- rule_set id=225 tenant_code=PTB01 rule_type=行政卷宗.行政许可.延续 current_version_id=426 status=active deleted_at=None +-- rule_set id=226 tenant_code=PTB01 rule_type=行政卷宗.行政许可.恢复营业 current_version_id=427 status=active deleted_at=None +-- rule_set id=227 tenant_code=PTB01 rule_type=行政卷宗.行政许可.收回 current_version_id=428 status=active deleted_at=None +-- rule_set id=228 tenant_code=PTB01 rule_type=行政卷宗.行政许可.新办 current_version_id=429 status=active deleted_at=None +-- rule_set id=229 tenant_code=PTB01 rule_type=行政卷宗.行政许可.歇业 current_version_id=430 status=active deleted_at=None +-- rule_set id=230 tenant_code=PTB01 rule_type=行政卷宗.行政许可.注销 current_version_id=431 status=active deleted_at=None +-- rule_set id=231 tenant_code=PTB01 rule_type=行政卷宗.行政许可.补办 current_version_id=432 status=active deleted_at=None + +-- rule_version id=1 rule_set_id=21 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=2 rule_set_id=22 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=3 rule_set_id=23 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=4 rule_set_id=24 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=5 rule_set_id=25 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=6 rule_set_id=26 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=7 rule_set_id=27 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=8 rule_set_id=28 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=9 rule_set_id=29 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=10 rule_set_id=30 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=11 rule_set_id=31 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=12 rule_set_id=32 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=13 rule_set_id=33 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=14 rule_set_id=34 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=15 rule_set_id=35 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=16 rule_set_id=36 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=17 rule_set_id=37 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=18 rule_set_id=38 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=19 rule_set_id=39 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=20 rule_set_id=40 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=21 rule_set_id=21 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=22 rule_set_id=22 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=23 rule_set_id=22 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=24 rule_set_id=22 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=25 rule_set_id=22 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=26 rule_set_id=22 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=27 rule_set_id=22 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=28 rule_set_id=22 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=29 rule_set_id=22 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=30 rule_set_id=21 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=31 rule_set_id=41 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=32 rule_set_id=44 version_no=v10 status=deprecated oss_url=rules/contract.entrust/v10/rules.yaml sha=92310866a9ee3030e3b4198623ab4dc45ac5dfdd0b2cb08d334622544eb6e599 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=97 rule_set_id=107 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=98 rule_set_id=126 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=99 rule_set_id=126 version_no=v2 status=rollback oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=100 rule_set_id=126 version_no=v3 status=deprecated oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=101 rule_set_id=108 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=102 rule_set_id=109 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=103 rule_set_id=110 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=104 rule_set_id=111 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=105 rule_set_id=112 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=106 rule_set_id=113 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=107 rule_set_id=114 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=108 rule_set_id=115 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=109 rule_set_id=116 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=110 rule_set_id=117 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=111 rule_set_id=118 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=112 rule_set_id=119 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=113 rule_set_id=120 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=114 rule_set_id=121 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=115 rule_set_id=122 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=116 rule_set_id=123 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=117 rule_set_id=124 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=118 rule_set_id=125 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=119 rule_set_id=127 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=120 rule_set_id=127 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=121 rule_set_id=127 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=122 rule_set_id=127 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=123 rule_set_id=127 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=124 rule_set_id=127 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=125 rule_set_id=127 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=126 rule_set_id=127 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=127 rule_set_id=127 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=128 rule_set_id=128 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=129 rule_set_id=129 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=130 rule_set_id=130 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=131 rule_set_id=131 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=132 rule_set_id=132 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=133 rule_set_id=133 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=134 rule_set_id=134 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=135 rule_set_id=135 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=136 rule_set_id=136 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=137 rule_set_id=137 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=138 rule_set_id=138 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=139 rule_set_id=139 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=140 rule_set_id=140 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=141 rule_set_id=141 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=142 rule_set_id=142 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=143 rule_set_id=143 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=144 rule_set_id=144 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=145 rule_set_id=145 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=146 rule_set_id=146 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=147 rule_set_id=147 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=148 rule_set_id=147 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=149 rule_set_id=147 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=150 rule_set_id=148 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=151 rule_set_id=148 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=152 rule_set_id=148 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=153 rule_set_id=148 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=154 rule_set_id=148 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=155 rule_set_id=148 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=156 rule_set_id=148 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=157 rule_set_id=148 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=158 rule_set_id=148 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=159 rule_set_id=149 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=160 rule_set_id=150 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=161 rule_set_id=151 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=162 rule_set_id=152 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=163 rule_set_id=153 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=164 rule_set_id=154 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=165 rule_set_id=155 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=166 rule_set_id=156 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=167 rule_set_id=157 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=168 rule_set_id=158 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=169 rule_set_id=159 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=170 rule_set_id=160 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=171 rule_set_id=161 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=172 rule_set_id=162 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=173 rule_set_id=163 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=174 rule_set_id=164 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=175 rule_set_id=165 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=176 rule_set_id=166 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=177 rule_set_id=167 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=178 rule_set_id=168 version_no=1.2 status=deprecated oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=179 rule_set_id=168 version_no=v2 status=rollback oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=180 rule_set_id=168 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=181 rule_set_id=169 version_no=0.1 status=deprecated oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=182 rule_set_id=170 version_no=1.0 status=deprecated oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=5a7a89f1e88e34c6afa9405010b1aaef517f56704cd264227d652b794e4a0acd deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=183 rule_set_id=171 version_no=1.0 status=deprecated oss_url=rules/contract.gift.general/1.0/rules.yaml sha=efeca05a6c0a0a1e1d113c781d38f6cd761d18513eb0c2274e9255e50955940e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=184 rule_set_id=172 version_no=2.0 status=deprecated oss_url=rules/contract.lease/2.0/rules.yaml sha=536265d6490c87bd7dfb66fdb0428a8164895bd368008073e74c788d2d3f1564 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=185 rule_set_id=173 version_no=1.0 status=deprecated oss_url=rules/contract.loan.general/1.0/rules.yaml sha=134cc339b7edfdc061c98becefd9e5f904d25f6e19f5a27664c46610650e07d6 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=186 rule_set_id=174 version_no=1.0 status=deprecated oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=d7d9e3b19e83716f067021fc4084a01cc0b1cc0df7f4a851faf8a0a3d33040ca deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=187 rule_set_id=175 version_no=2.1 status=deprecated oss_url=rules/contract.sale/2.1/rules.yaml sha=e246bf9554003b078c6cccfde2ac9deecad1fbe083c536edf21735f613aeae7d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=188 rule_set_id=176 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=e96c7925535ab0dee8e1cdfa0db5ab398c9951adcda8b680c713d66cd6fa5878 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=189 rule_set_id=177 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=190 rule_set_id=178 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=191 rule_set_id=179 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=192 rule_set_id=180 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=193 rule_set_id=181 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=194 rule_set_id=182 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=195 rule_set_id=183 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=196 rule_set_id=184 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=197 rule_set_id=185 version_no=1.0 status=deprecated oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=198 rule_set_id=186 version_no=1.0 status=deprecated oss_url=rules/contract.tech/1.0/rules.yaml sha=95aa3a0be32b44d5594d5ec101d6568480c36a71a1aeec31951680d8aa14e05f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=199 rule_set_id=187 version_no=0.1 status=deprecated oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=7d59151c9a41903eca748c0f7bb283ddffad699a68c963af655a84e8fe621745 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=200 rule_set_id=188 version_no=1.2 status=rollback oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=201 rule_set_id=188 version_no=v2 status=deprecated oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=202 rule_set_id=188 version_no=v3 status=rollback oss_url=rules/contract.construction.general/v3/rules.yaml sha=a5c21fac8c4352fcf75c6b17a8ec5c6ff71b54b453a3338b3f5a68b6f496f355 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=203 rule_set_id=189 version_no=v5 status=rollback oss_url=rules/contract.entrust/v5/rules.yaml sha=fa0e241874262f7229387da9e352073dc3decfe3b8048e559c35cad0ff4b2b49 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=204 rule_set_id=189 version_no=2.0 status=rollback oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=205 rule_set_id=189 version_no=v8 status=deprecated oss_url=rules/contract.entrust/v8/rules.yaml sha=cf1938696438a2ae6a8b584207f99a4f167512383e456dd0041a2d9287db38b0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=206 rule_set_id=189 version_no=v9 status=rollback oss_url=rules/contract.entrust/v9/rules.yaml sha=81d41fe8d27d394e4372a0668a2acb8975003975929d1c5f56c379c41cc23d33 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=207 rule_set_id=189 version_no=v6 status=deprecated oss_url=rules/contract.entrust/v6/rules.yaml sha=86fe184ffcc2a0ef8639f91632f0859519e96fb96f2f7d29b0f6e2343d03ab07 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=208 rule_set_id=189 version_no=v7 status=deprecated oss_url=rules/contract.entrust/v7/rules.yaml sha=ba305b20965a5ed794539fe23a3c0534c9149380fc3a67d977ddfe7f0ecbf9f8 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=209 rule_set_id=189 version_no=v4 status=deprecated oss_url=rules/contract.entrust/v4/rules.yaml sha=d400d2801a42b94ad87b87bbad291b7f036acf0808a6dbc025336dedc181d21f deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=210 rule_set_id=189 version_no=v3 status=rollback oss_url=rules/contract.entrust/v3/rules.yaml sha=9d03f9917d0d401efcbb120abdc48a7e03783cac83364692bce32c2eece8a40e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=211 rule_set_id=189 version_no=v2 status=rollback oss_url=rules/contract.entrust/v2/rules.yaml sha=5948e85e7d965b0d70710b5fef6acde5eb2a633993f3ada971447bd51c512395 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=212 rule_set_id=168 version_no=v4 status=rollback oss_url=rules/contract.construction.general/v4/rules.yaml sha=5b058dbb0dd14a31132110f04e649d26cc2d9f544ec2f8ffa56c4ada1917cd13 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=213 rule_set_id=22 version_no=v10 status=draft oss_url=rules/contract.entrust/v10/rules.yaml sha=0481fb582bf30fb137d9552cecdae22fd6ee525954b893ccaec386b186caabcc deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=214 rule_set_id=22 version_no=v11 status=draft oss_url=rules/contract.entrust/v11/rules.yaml sha=4fb270e13c9c3ab9d771807f9f333232a9cf78567163521606165b0889200c3e deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=215 rule_set_id=127 version_no=pytest-vm-1779365463 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779365463/rules.yaml sha=59763ad2915c90871dfa641264b74fe22f164b7590bd26a71f448dccba66d4e0 deleted_at=2026-05-21 13:46:08.095958+00:00 +-- rule_version id=216 rule_set_id=188 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=217 rule_set_id=188 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=218 rule_set_id=188 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=219 rule_set_id=189 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=220 rule_set_id=189 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=221 rule_set_id=189 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=222 rule_set_id=189 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=223 rule_set_id=189 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=224 rule_set_id=189 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=225 rule_set_id=189 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=226 rule_set_id=189 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=227 rule_set_id=189 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=228 rule_set_id=187 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=229 rule_set_id=170 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=230 rule_set_id=171 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=231 rule_set_id=172 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=232 rule_set_id=173 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=233 rule_set_id=174 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=234 rule_set_id=175 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=235 rule_set_id=186 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=236 rule_set_id=169 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=237 rule_set_id=176 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=238 rule_set_id=177 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=239 rule_set_id=178 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=240 rule_set_id=179 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=241 rule_set_id=180 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=242 rule_set_id=181 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=243 rule_set_id=182 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=244 rule_set_id=183 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=245 rule_set_id=184 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=246 rule_set_id=185 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=247 rule_set_id=168 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=248 rule_set_id=168 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=249 rule_set_id=168 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=250 rule_set_id=44 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=251 rule_set_id=44 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=252 rule_set_id=44 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=253 rule_set_id=44 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=254 rule_set_id=44 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=255 rule_set_id=44 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=256 rule_set_id=44 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=257 rule_set_id=44 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=258 rule_set_id=44 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=259 rule_set_id=167 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=260 rule_set_id=150 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=261 rule_set_id=151 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=262 rule_set_id=152 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=263 rule_set_id=153 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=264 rule_set_id=154 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=265 rule_set_id=155 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=266 rule_set_id=166 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=267 rule_set_id=149 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=268 rule_set_id=156 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=269 rule_set_id=157 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=270 rule_set_id=158 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=271 rule_set_id=159 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=272 rule_set_id=160 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=273 rule_set_id=161 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=274 rule_set_id=162 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=275 rule_set_id=163 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=276 rule_set_id=164 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=277 rule_set_id=165 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=278 rule_set_id=126 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=279 rule_set_id=126 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=280 rule_set_id=126 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=281 rule_set_id=127 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=282 rule_set_id=127 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=283 rule_set_id=127 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=284 rule_set_id=127 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=285 rule_set_id=127 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=286 rule_set_id=127 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=287 rule_set_id=127 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=288 rule_set_id=127 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=289 rule_set_id=127 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=290 rule_set_id=125 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=291 rule_set_id=108 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=292 rule_set_id=109 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=293 rule_set_id=110 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=294 rule_set_id=111 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=295 rule_set_id=112 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=296 rule_set_id=113 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=297 rule_set_id=124 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=298 rule_set_id=107 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=299 rule_set_id=114 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=300 rule_set_id=115 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=301 rule_set_id=116 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=302 rule_set_id=117 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=303 rule_set_id=118 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=304 rule_set_id=119 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=305 rule_set_id=120 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=306 rule_set_id=121 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=307 rule_set_id=122 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=308 rule_set_id=123 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=309 rule_set_id=21 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=310 rule_set_id=21 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=311 rule_set_id=21 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=312 rule_set_id=22 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=313 rule_set_id=22 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=314 rule_set_id=22 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=315 rule_set_id=22 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=316 rule_set_id=22 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=317 rule_set_id=22 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=318 rule_set_id=22 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=319 rule_set_id=22 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=320 rule_set_id=22 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=321 rule_set_id=23 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=322 rule_set_id=24 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=323 rule_set_id=25 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=324 rule_set_id=26 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=325 rule_set_id=27 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=326 rule_set_id=28 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=327 rule_set_id=29 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=328 rule_set_id=30 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=329 rule_set_id=41 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=330 rule_set_id=31 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=331 rule_set_id=32 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=332 rule_set_id=33 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=333 rule_set_id=34 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=334 rule_set_id=35 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=335 rule_set_id=36 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=336 rule_set_id=37 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=337 rule_set_id=38 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=338 rule_set_id=39 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=339 rule_set_id=40 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=340 rule_set_id=147 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=341 rule_set_id=147 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=342 rule_set_id=147 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=343 rule_set_id=148 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=344 rule_set_id=148 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=345 rule_set_id=148 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=346 rule_set_id=148 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=347 rule_set_id=148 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=348 rule_set_id=148 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=349 rule_set_id=148 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=350 rule_set_id=148 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=351 rule_set_id=148 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=352 rule_set_id=146 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=353 rule_set_id=129 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=354 rule_set_id=130 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=355 rule_set_id=131 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=356 rule_set_id=132 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=357 rule_set_id=133 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=358 rule_set_id=134 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=359 rule_set_id=145 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=360 rule_set_id=128 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=361 rule_set_id=135 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=362 rule_set_id=136 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=363 rule_set_id=137 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=364 rule_set_id=138 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=365 rule_set_id=139 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=366 rule_set_id=140 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=367 rule_set_id=141 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=368 rule_set_id=142 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=369 rule_set_id=143 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=370 rule_set_id=144 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=371 rule_set_id=190 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=372 rule_set_id=191 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=373 rule_set_id=192 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=374 rule_set_id=192 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=375 rule_set_id=192 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=376 rule_set_id=193 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=377 rule_set_id=193 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=378 rule_set_id=193 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=379 rule_set_id=193 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=380 rule_set_id=193 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=381 rule_set_id=193 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=382 rule_set_id=193 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=383 rule_set_id=193 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=384 rule_set_id=193 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=385 rule_set_id=194 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=386 rule_set_id=195 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=387 rule_set_id=196 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=388 rule_set_id=197 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=389 rule_set_id=198 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=390 rule_set_id=199 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=391 rule_set_id=200 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=392 rule_set_id=201 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=393 rule_set_id=202 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=394 rule_set_id=203 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=395 rule_set_id=204 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=396 rule_set_id=205 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=397 rule_set_id=206 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=398 rule_set_id=207 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=399 rule_set_id=208 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=400 rule_set_id=209 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=401 rule_set_id=210 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=402 rule_set_id=211 version_no=1.0 status=published oss_url=rules/contract.gift.charity/1.0/rules.yaml sha=4f4c2b64cc84cf791be770b785986cc67f4ef864174f95d9ba7e4a84fdadc8cc deleted_at=None +-- rule_version id=403 rule_set_id=212 version_no=0.1 status=published oss_url=rules/govdoc.general/0.1/rules.yaml sha=cd8c93b16641aeda9bd403b0159d6443a5a68fb1f602a2adbcdd63a92e5d3687 deleted_at=None +-- rule_version id=404 rule_set_id=213 version_no=v2 status=draft oss_url=rules/contract.construction.general/v2/rules.yaml sha=ec77babbfe200bd63a6101d273e6318cc5eb492b86ed4829c239e6508ff91534 deleted_at=None +-- rule_version id=405 rule_set_id=213 version_no=v3 status=draft oss_url=rules/contract.construction.general/v3/rules.yaml sha=b8b03368e540e86bec8cff3dd3b07dacc3bded4dba0f07f25d9454b713f249b8 deleted_at=None +-- rule_version id=406 rule_set_id=213 version_no=1.2 status=published oss_url=rules/contract.construction.general/1.2/rules.yaml sha=56117d4aaf76837a9b913560dc21cbb7d5c2469883685a41b7e153b059ef4592 deleted_at=None +-- rule_version id=407 rule_set_id=214 version_no=v2 status=draft oss_url=rules/contract.entrust/v2/rules.yaml sha=2d5490d16057697e60099d6cec33d51aaac2f748fc0038ae154ae2dd67f2d5a2 deleted_at=None +-- rule_version id=408 rule_set_id=214 version_no=v3 status=draft oss_url=rules/contract.entrust/v3/rules.yaml sha=18025aa0035f08f571775c2236d23ce0b6c23b0c32dd7f3ece8f97ffe81b4944 deleted_at=None +-- rule_version id=409 rule_set_id=214 version_no=v4 status=draft oss_url=rules/contract.entrust/v4/rules.yaml sha=212c1a3724b14dec4074c4e4ea62485c0b07ac5d772bce8e9a6108efe312ec05 deleted_at=None +-- rule_version id=410 rule_set_id=214 version_no=v5 status=draft oss_url=rules/contract.entrust/v5/rules.yaml sha=5424c16a3a35eb7c44131904a99e97203b41e02148b8eaba1df9782bc4309cfc deleted_at=None +-- rule_version id=411 rule_set_id=214 version_no=v6 status=draft oss_url=rules/contract.entrust/v6/rules.yaml sha=0ee30fc1e3fdaab53f47c4a8cc3479b89fabf1be821ee9b65cea9ea223a40d35 deleted_at=None +-- rule_version id=412 rule_set_id=214 version_no=v7 status=draft oss_url=rules/contract.entrust/v7/rules.yaml sha=75c817acc45e7661aab5171a987ffc9e602e79353488c89bc12fcb2f749791df deleted_at=None +-- rule_version id=413 rule_set_id=214 version_no=v8 status=draft oss_url=rules/contract.entrust/v8/rules.yaml sha=cae719d588766213e251b141d4b910388046883e135b173dae2c71888ebe4a0f deleted_at=None +-- rule_version id=414 rule_set_id=214 version_no=v9 status=draft oss_url=rules/contract.entrust/v9/rules.yaml sha=11f41652de07617382eaa68b401cdaa2f7ff2a46ac61a903e8b44cf240768784 deleted_at=None +-- rule_version id=415 rule_set_id=214 version_no=2.0 status=published oss_url=rules/contract.entrust/2.0/rules.yaml sha=5b4653d245ef0c1897bc366baa4d18e0c5ae28badd1175c04c3841c0a4b06a17 deleted_at=None +-- rule_version id=416 rule_set_id=215 version_no=0.1 status=published oss_url=rules/contract.evaluation.delegation/0.1/rules.yaml sha=f2159624c569d6f18f37afb8bf6fa7ea099cc2e019cbf8b3bf3a2ce25d54a727 deleted_at=None +-- rule_version id=417 rule_set_id=216 version_no=1.0 status=published oss_url=rules/contract.gift.general/1.0/rules.yaml sha=dd268a9c38d6143523f5afeddffeacaa3d396111d0eec987abe299ea9756df6b deleted_at=None +-- rule_version id=418 rule_set_id=217 version_no=2.0 status=published oss_url=rules/contract.lease/2.0/rules.yaml sha=5da7fe94f3fa7ead4c333fb7d273ba9e22ed7002ad5d7e9c6338418fcbad3c6b deleted_at=None +-- rule_version id=419 rule_set_id=218 version_no=1.0 status=published oss_url=rules/contract.loan.general/1.0/rules.yaml sha=426d0f66acaf1bac1f9bd18fda2187c2e2bffe5530aff8c76cc3cc4641892d23 deleted_at=None +-- rule_version id=420 rule_set_id=219 version_no=1.0 status=published oss_url=rules/contract.purchase.general/1.0/rules.yaml sha=e60b679aa58958187d193d00097611c87d0bfd19f6b910f1d587fd95dd35826b deleted_at=None +-- rule_version id=421 rule_set_id=220 version_no=2.1 status=published oss_url=rules/contract.sale/2.1/rules.yaml sha=698b6df771cad864d3979ba4f5f134bf9bfe6af2f6b4aea85c8588c292ebbafc deleted_at=None +-- rule_version id=422 rule_set_id=221 version_no=1.0 status=published oss_url=rules/contract.tech/1.0/rules.yaml sha=c5ab06b6df9542715705aac6fbb0defcad35ae76ee9dea4125f57d0585b7d8ec deleted_at=None +-- rule_version id=423 rule_set_id=222 version_no=1.0 status=published oss_url=rules/行政卷宗.行政处罚/1.0/rules.yaml sha=f504ac3eccb0c148ca092d40b7bb2a87b95915b6e708395f4be00b8d337179de deleted_at=None +-- rule_version id=424 rule_set_id=223 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.停业/1.0/rules.yaml sha=b14ccd9f276943a6159355226f08934263bc95c6fa514d51a91a2d4ac1a02333 deleted_at=None +-- rule_version id=425 rule_set_id=224 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.变更/1.0/rules.yaml sha=44bf8354cbe556d03ea89e0568e0db955675fe7ade3cc1f712779195c26d67eb deleted_at=None +-- rule_version id=426 rule_set_id=225 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.延续/1.0/rules.yaml sha=2b1daa8b579f7ce8cb809dcda2035d46f82d75363357573a4cd3526ac20549fb deleted_at=None +-- rule_version id=427 rule_set_id=226 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.恢复营业/1.0/rules.yaml sha=f175e1fa7a4ec1b24991a8d628085bb1fbc40a60012a91d1c2364fd4638b8a4d deleted_at=None +-- rule_version id=428 rule_set_id=227 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.收回/1.0/rules.yaml sha=f0d1b780ef136356c51132d9d1da1591c89ad2a201a80d2dc533e76aebc34155 deleted_at=None +-- rule_version id=429 rule_set_id=228 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.新办/1.0/rules.yaml sha=89cdbcfd13549f3e5b8d7402d2a46bfcd05a8108b3193210ae176f3aeb3ab79e deleted_at=None +-- rule_version id=430 rule_set_id=229 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.歇业/1.0/rules.yaml sha=cb3f1ca8e5386176a2d9c334720dee0570626644a8fb5ebb281ebd92fc2b77a9 deleted_at=None +-- rule_version id=431 rule_set_id=230 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.注销/1.0/rules.yaml sha=3e07da60e91a20168ba39ca906b9d8b1b9d1fa1841c40d4a63563ef9660e7906 deleted_at=None +-- rule_version id=432 rule_set_id=231 version_no=1.0 status=published oss_url=rules/行政卷宗.行政许可.补办/1.0/rules.yaml sha=56af0893c1d458bbd42eb19b9e76d5394350429a580c9fecf79a66d2d78ca1ed deleted_at=None +-- rule_version id=433 rule_set_id=127 version_no=pytest-vm-1779371496 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779371496/rules.yaml sha=6bb8ef6ffec27b920c9f713243e85fd19f858c3cb1b6a3216819a5c167a7bfaf deleted_at=None +-- rule_version id=434 rule_set_id=127 version_no=pytest-vm-1779371996 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779371996/rules.yaml sha=4ba3e8f648ffd28d18a97d52c1c826d2ea6a6ef582c15e4e1f2bc1f1fb31e2e5 deleted_at=None +-- rule_version id=435 rule_set_id=127 version_no=pytest-vm-1779372327 status=rollback oss_url=rules/contract.entrust/pytest-vm-1779372327/rules.yaml sha=82efcd120f121d7ba6f9c6c3b310d3431ff69372e328de30c3ec73ad77b8d0cf deleted_at=None diff --git a/fastapi_admin/config/__init__.py b/fastapi_admin/config/__init__.py index 9ded1f5..9864259 100644 --- a/fastapi_admin/config/__init__.py +++ b/fastapi_admin/config/__init__.py @@ -13,7 +13,7 @@ from ._loader import load_config as _load_config # 优先加载 TOML → os.environ(必须在 Settings 实例化之前) _load_config() -from ._settings import app, jwt, db, redis, oss, llm, vlm, embedding, ocr, leaudit as _leaudit # noqa: E402 +from ._settings import app, jwt, db, redis, oss, llm, vlm, embedding, ocr, leaudit as _leaudit, qichacha # noqa: E402 def _export_settings(instance: object, prefix: str = "") -> dict[str, object]: @@ -51,6 +51,7 @@ _VLM = _export_settings(vlm) _EMBEDDING = _export_settings(embedding) _OCR = _export_settings(ocr) _LEAUDIT = _export_settings(_leaudit) +_QICHACHA = _export_settings(qichacha) # 将所有变量注入当前模块的全局命名空间 _ALL = {} @@ -64,6 +65,7 @@ _ALL.update(_VLM) _ALL.update(_EMBEDDING) _ALL.update(_OCR) _ALL.update(_LEAUDIT) +_ALL.update(_QICHACHA) globals().update(_ALL) diff --git a/fastapi_admin/config/_settings.py b/fastapi_admin/config/_settings.py index 06dcb47..c637439 100644 --- a/fastapi_admin/config/_settings.py +++ b/fastapi_admin/config/_settings.py @@ -130,6 +130,30 @@ class LeauditSettings(_Base): LEAUDIT_PAGE_QUALITY_QUEUE_URGENT: str = "leaudit.page_quality.urgent" +class QichachaSettings(_Base): + """企查查配置 [QICHACHA]。""" + + QICHACHA_APP_KEY: str = "" + QICHACHA_SECRET_KEY: str = "" + QICHACHA_BASE_URL: str = "https://api.qichacha.com" + QICHACHA_ENTERPRISE_PATH: str = "/ECIV4/GetBasicDetailsByName" + QICHACHA_DISHONESTY_PATH: str = "/ShixinCheck/GetList" + QICHACHA_TIMEOUT: int = 30 + QICHACHA_MAX_RETRIES: int = 3 + QICHACHA_RETRY_DELAY: float = 1.0 + QICHACHA_CACHE_DAYS: int = 30 + + @property + def QICHACHA_ENTERPRISE_URL(self) -> str: + """企查查工商信息接口完整 URL。""" + return f"{self.QICHACHA_BASE_URL.rstrip('/')}{self.QICHACHA_ENTERPRISE_PATH}" + + @property + def QICHACHA_DISHONESTY_URL(self) -> str: + """企查查失信核查接口完整 URL。""" + return f"{self.QICHACHA_BASE_URL.rstrip('/')}{self.QICHACHA_DISHONESTY_PATH}" + + # 实例化所有 Settings app = AppSettings() jwt = JwtSettings() @@ -141,3 +165,4 @@ vlm = VlmSettings() embedding = EmbeddingSettings() ocr = OcrSettings() leaudit = LeauditSettings() +qichacha = QichachaSettings() diff --git a/fastapi_common/fastapi_common_web/exception/QichachaException.py b/fastapi_common/fastapi_common_web/exception/QichachaException.py new file mode 100644 index 0000000..83b62d7 --- /dev/null +++ b/fastapi_common/fastapi_common_web/exception/QichachaException.py @@ -0,0 +1,7 @@ +"""企查查模块异常。""" + +from fastapi_common.fastapi_common_web.exception.Base.BusinessException import BusinessException + + +class QichachaException(BusinessException): + """企查查模块业务异常。""" diff --git a/fastapi_modules/fastapi_leaudit/controllers/crossReviewController.py b/fastapi_modules/fastapi_leaudit/controllers/crossReviewController.py index fa40042..29e231b 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/crossReviewController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/crossReviewController.py @@ -76,7 +76,9 @@ class CrossReviewController(BaseController): """查询当前用户参与的交叉评查任务。""" if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["task_read"]]): return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看交叉评查任务权限", "data": None}) - Data = await self.CrossReviewService.GetUserTasks(CurrentUserId=int(payload["user_id"]), Body=Body) + UserId = int(payload["user_id"]) + CanViewProgress = await self._check_permission(UserId, [self._PERMISSIONS["progress_view"]]) + Data = await self.CrossReviewService.GetUserTasks(CurrentUserId=UserId, Body=Body, CanViewProgress=CanViewProgress) return Result.success(data=Data) @self.router.get("/tasks/{TaskId}/progress", response_model=Result[CrossReviewTaskProgressVO]) diff --git a/fastapi_modules/fastapi_leaudit/controllers/documentController.py b/fastapi_modules/fastapi_leaudit/controllers/documentController.py index 82088fb..41e8d08 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/documentController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/documentController.py @@ -4,6 +4,7 @@ import json from typing import Any from fastapi import Depends, File, Form, Query, UploadFile +from fastapi.responses import JSONResponse from pydantic import BaseModel, Field from sqlalchemy import text @@ -34,6 +35,8 @@ from fastapi_modules.fastapi_leaudit.domian.vo.reviewPointVo import ( ) from fastapi_modules.fastapi_leaudit.services import IDocumentService from fastapi_modules.fastapi_leaudit.services.impl.documentServiceImpl import DocumentServiceImpl +from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl +from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService class QueueStatusVO(BaseModel): @@ -51,6 +54,8 @@ class ReviewPointAuditDTO(BaseModel): class DocumentController(BaseController): """文档控制器。""" + _CROSS_REVIEW_DOCUMENT_READ_PERMISSION = "cross_review:document:read" + @staticmethod def _tenant_context(payload: dict[str, Any]) -> dict[str, str | None]: return { @@ -61,6 +66,7 @@ class DocumentController(BaseController): def __init__(self): super().__init__(prefix="", tags=["文档"]) self.DocumentService: IDocumentService = DocumentServiceImpl() + self.PermissionService: IPermissionService = PermissionServiceImpl() @self.router.post("/upload", response_model=Result[DocumentUploadVO]) async def UploadDocument( @@ -69,6 +75,8 @@ class DocumentController(BaseController): typeId: int | None = Form(None, description="文档类型ID"), typeCode: str | None = Form(None, description="文档类型编码"), groupId: int | None = Form(None, description="二级分组ID"), + entryModuleId: int | None = Form(None, description="入口模块ID"), + entry_module_id: int | None = Form(None, description="入口模块ID,兼容蛇形字段"), region: str | None = Form(None, description="所属租户/地区"), tenant_code: str | None = Form(None, description="租户编码"), fileRole: str = Form("primary", description="文件角色"), @@ -97,6 +105,7 @@ class DocumentController(BaseController): TypeId=typeId, TypeCode=typeCode, GroupId=groupId, + EntryModuleId=entryModuleId or entry_module_id, Region=region, FileRole=fileRole, CreatedBy=int(payload["user_id"]), @@ -194,7 +203,11 @@ class DocumentController(BaseController): payload: dict[str, Any] = Depends(verify_access_token), ): """获取单个文档详情(带数据隔离校验)。""" - Data = await self.DocumentService.GetDocument(CurrentUserId=int(payload["user_id"]), Id=DocumentId) + userId = int(payload["user_id"]) + deniedResponse = await self._deny_cross_review_document_without_permission(userId, DocumentId) + if deniedResponse: + return deniedResponse + Data = await self.DocumentService.GetDocument(CurrentUserId=userId, Id=DocumentId) return Result.success(data=Data) @self.router.get("/v3/review-points/{DocumentId}", response_model=Result[ReviewPointsAggregateVO]) @@ -203,7 +216,11 @@ class DocumentController(BaseController): payload: dict[str, Any] = Depends(verify_access_token), ): """获取评查详情页聚合数据(带数据隔离校验)。""" - Data = await self.DocumentService.GetReviewPoints(CurrentUserId=int(payload["user_id"]), DocumentId=DocumentId) + userId = int(payload["user_id"]) + deniedResponse = await self._deny_cross_review_document_without_permission(userId, DocumentId) + if deniedResponse: + return deniedResponse + Data = await self.DocumentService.GetReviewPoints(CurrentUserId=userId, DocumentId=DocumentId) return Result.success(data=Data) @self.router.patch("/v3/review-points/{ReviewPointResultId}/audit", response_model=Result[ReviewPointAuditVO]) @@ -400,3 +417,17 @@ class DocumentController(BaseController): }, ) ) + + async def _deny_cross_review_document_without_permission(self, UserId: int, DocumentId: int) -> JSONResponse | None: + if not await self.DocumentService.IsCrossReviewDocument(DocumentId): + return None + hasPermission = await self.PermissionService.HasAnyPermission( + UserId=UserId, + PermissionKeys=[self._CROSS_REVIEW_DOCUMENT_READ_PERMISSION], + ) + if hasPermission: + return None + return JSONResponse( + status_code=403, + content={"code": 403, "msg": "当前用户没有查看交叉评查结果权限", "data": None}, + ) diff --git a/fastapi_modules/fastapi_leaudit/controllers/evaluationPointController.py b/fastapi_modules/fastapi_leaudit/controllers/evaluationPointController.py index 41d0d61..5adfa9f 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/evaluationPointController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/evaluationPointController.py @@ -1,155 +1,40 @@ -"""评查点控制器。""" +"""Legacy evaluation point API. + +The current rule configuration flow is backed by leaudit_evaluation_point_groups +and rule version tables. The old evaluation_points table is no longer present +in the active schema, so keep this route explicit and non-destructive. +""" -from fastapi import Depends, Query from fastapi.responses import JSONResponse -from fastapi_common.fastapi_common_security.security import verify_access_token from fastapi_common.fastapi_common_web.controller import BaseController -from fastapi_modules.fastapi_leaudit.domian.Dto.evaluationPointDto import ( - EvaluationPointCreateDTO, - EvaluationPointUpdateDTO, -) -from fastapi_modules.fastapi_leaudit.services.evaluationPointService import IEvaluationPointService -from fastapi_modules.fastapi_leaudit.services.impl.evaluationPointServiceImpl import EvaluationPointServiceImpl -from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl -from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService class EvaluationPointController(BaseController): - """评查点控制器。""" - - _PERMISSIONS = { - "list": "evaluation_point:list:read", - "detail": "evaluation_point:detail:read", - "create": "evaluation_point:create:write", - "update": "evaluation_point:update:write", - "delete": "evaluation_point:delete:delete", - } - - @staticmethod - def _tenant_context(payload: dict) -> dict[str, str | None]: - return { - "UserArea": payload.get("area"), - "UserRole": payload.get("user_role"), - "TenantCode": payload.get("tenant_code"), - "TenantName": payload.get("tenant_name"), - } + """Deprecated legacy evaluation point controller.""" def __init__(self): - super().__init__(prefix="/v3/evaluation-points", tags=["评查点"]) - self.PointService: IEvaluationPointService = EvaluationPointServiceImpl() - self.PermissionService: IPermissionService = PermissionServiceImpl() + super().__init__(prefix="/v3/evaluation-points", tags=["旧评查点接口"]) - @self.router.get("") - async def ListEvaluationPoints( - name: str | None = Query(None, description="名称模糊搜索"), - code: str | None = Query(None, description="编码模糊搜索"), - risk: str | None = Query(None, description="风险等级"), - is_enabled: bool | None = Query(None, description="是否启用"), - evaluation_point_groups_pid: int | None = Query(None, description="一级分组ID"), - evaluation_point_groups_id: int | None = Query(None, description="二级分组ID"), - document_attribute_type: str | None = Query(None, description="文档属性类型"), - area: str | None = Query(None, description="地区/兼容租户展示值"), - tenant_code: str | None = Query(None, description="租户编码"), - tenant_name: str | None = Query(None, description="租户名称(兼容筛选)"), - page: int = Query(1, ge=1, description="页码"), - page_size: int = Query(20, ge=1, le=500, description="分页大小"), - payload: dict = Depends(verify_access_token), - ): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["list"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点查看权限", "data": None}) - tenant_context = self._tenant_context(payload) - data = await self.PointService.ListPoints( - int(payload["user_id"]), - tenant_context["UserArea"], - tenant_context["UserRole"], - tenant_context["TenantCode"], - tenant_context["TenantName"], - name, - code, - risk, - is_enabled, - evaluation_point_groups_pid, - evaluation_point_groups_id, - document_attribute_type, - area, - tenant_code, - tenant_name, - page, - page_size, - ) - return JSONResponse(status_code=200, content=data.model_dump()) + @self.router.api_route("", methods=["GET", "POST"]) + async def LegacyEvaluationPointsRoot(): + return self._gone() - @self.router.get("/attribute-types") - async def GetEvaluationPointAttributeTypes(payload: dict = Depends(verify_access_token)): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["list"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点查看权限", "data": None}) - data = await self.PointService.GetAttributeTypes() - return JSONResponse(status_code=200, content=data.model_dump()) + @self.router.api_route("/attribute-types", methods=["GET"]) + async def LegacyEvaluationPointAttributeTypes(): + return self._gone() - @self.router.get("/{PointId}") - async def GetEvaluationPoint(PointId: int, payload: dict = Depends(verify_access_token)): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["detail"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点查看权限", "data": None}) - tenant_context = self._tenant_context(payload) - data = await self.PointService.GetPoint( - int(payload["user_id"]), - tenant_context["UserArea"], - tenant_context["UserRole"], - tenant_context["TenantCode"], - tenant_context["TenantName"], - PointId, - ) - return JSONResponse(status_code=200, content=data.model_dump()) + @self.router.api_route("/{PointId}", methods=["GET", "PUT", "DELETE"]) + async def LegacyEvaluationPointDetail(PointId: int): + return self._gone() - @self.router.post("") - async def CreateEvaluationPoint(body: EvaluationPointCreateDTO, payload: dict = Depends(verify_access_token)): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["create"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建评查点权限", "data": None}) - tenant_context = self._tenant_context(payload) - data = await self.PointService.CreatePoint( - int(payload["user_id"]), - tenant_context["UserArea"], - tenant_context["UserRole"], - tenant_context["TenantCode"], - tenant_context["TenantName"], - body, - ) - return JSONResponse(status_code=200, content=data.model_dump()) - - @self.router.put("/{PointId}") - async def UpdateEvaluationPoint(PointId: int, body: EvaluationPointUpdateDTO, payload: dict = Depends(verify_access_token)): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["update"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新评查点权限", "data": None}) - tenant_context = self._tenant_context(payload) - data = await self.PointService.UpdatePoint( - int(payload["user_id"]), - tenant_context["UserArea"], - tenant_context["UserRole"], - tenant_context["TenantCode"], - tenant_context["TenantName"], - PointId, - body, - ) - return JSONResponse(status_code=200, content=data.model_dump()) - - @self.router.delete("/{PointId}") - async def DeleteEvaluationPoint(PointId: int, payload: dict = Depends(verify_access_token)): - if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["delete"]]): - return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除评查点权限", "data": None}) - tenant_context = self._tenant_context(payload) - data = await self.PointService.DeletePoint( - int(payload["user_id"]), - tenant_context["UserArea"], - tenant_context["UserRole"], - tenant_context["TenantCode"], - tenant_context["TenantName"], - PointId, - ) - return JSONResponse(status_code=200, content=data.model_dump()) - - async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool: - for permission_key in permission_keys: - if await self.PermissionService.CheckPermission(user_id, permission_key): - return True - return False + @staticmethod + def _gone() -> JSONResponse: + return JSONResponse( + status_code=410, + content={ + "code": 410, + "msg": "旧评查点接口已下线,请使用规则组/规则配置接口", + "data": None, + }, + ) diff --git a/fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py b/fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py index c28eae0..c9605ed 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py @@ -35,24 +35,26 @@ class EvaluationPointGroupController(BaseController): code: str | None = Query(None, description="分组编码模糊搜索"), is_enabled: bool | None = Query(None, description="是否启用"), pid: int | None = Query(None, description="父分组ID,0 表示一级分组"), + entry_module_id: int | None = Query(None, description="入口模块ID"), page: int = Query(1, ge=1, description="页码"), page_size: int = Query(20, ge=1, le=500, description="分页大小"), payload: dict = Depends(verify_access_token), ): if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]): return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None}) - data = await self.GroupService.ListGroups(name, code, is_enabled, pid, page, page_size, int(payload["user_id"])) + data = await self.GroupService.ListGroups(name, code, is_enabled, pid, page, page_size, int(payload["user_id"]), entry_module_id) return JSONResponse(status_code=200, content=data.model_dump()) @self.router.get("/all") async def ListAllEvaluationPointGroups( include_disabled: bool = Query(False, description="是否包含禁用分组"), with_rule_count: bool = Query(True, description="是否返回评查点数"), + entry_module_id: int | None = Query(None, description="入口模块ID"), payload: dict = Depends(verify_access_token), ): if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]): return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None}) - data = await self.GroupService.ListAllGroups(include_disabled, with_rule_count, int(payload["user_id"])) + data = await self.GroupService.ListAllGroups(include_disabled, with_rule_count, int(payload["user_id"]), entry_module_id) return JSONResponse(status_code=200, content=[item.model_dump() for item in data]) @self.router.get("/by-document-types") diff --git a/fastapi_modules/fastapi_leaudit/controllers/govdocController.py b/fastapi_modules/fastapi_leaudit/controllers/govdocController.py index 15663c8..6b642ad 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/govdocController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/govdocController.py @@ -8,6 +8,7 @@ from __future__ import annotations from typing import Any from fastapi import Depends, File, Form, Query, UploadFile +from fastapi.responses import JSONResponse from fastapi_common.fastapi_common_security.security import verify_access_token from fastapi_common.fastapi_common_web.controller import BaseController @@ -15,6 +16,8 @@ from fastapi_common.fastapi_common_web.domain.responses import Result from fastapi_modules.fastapi_leaudit.services import IGovdocService from fastapi_modules.fastapi_leaudit.services.impl.govdocServiceImpl import GovdocServiceImpl +from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl +from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService class GovdocController(BaseController): @@ -23,6 +26,7 @@ class GovdocController(BaseController): def __init__(self): super().__init__(prefix="/govdoc", tags=["内部公文"]) self.GovdocService: IGovdocService = GovdocServiceImpl() + self.PermissionService: IPermissionService = PermissionServiceImpl() # ── 文档 ────────────────────────────────────────── @@ -30,6 +34,7 @@ class GovdocController(BaseController): async def UploadDocument( file: UploadFile = File(...), typeId: int | None = Form(default=None), + entry_module_id: int | None = Form(default=None, description="入口模块ID"), region: str | None = Form(default=None, description="兼容保留字段:租户展示值/旧地区"), tenant_code: str | None = Form(default=None, description="租户编码"), autoRun: bool = Form(default=True), @@ -41,9 +46,12 @@ class GovdocController(BaseController): 创建文档主档记录,engine_type 标记为 govdoc,可选自动触发审查。 """ + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "govdoc:document:create"): + return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有上传公文权限", "data": None}) result = await self.GovdocService.UploadDocument( file=file, typeId=typeId, + entryModuleId=entry_module_id, region=region, tenantCode=tenant_code, autoRun=autoRun, @@ -61,6 +69,9 @@ class GovdocController(BaseController): fileExt: str | None = Query(default=None), region: str | None = Query(default=None, description="兼容保留字段:租户展示值/旧地区"), tenant_code: str | None = Query(default=None, description="租户编码"), + entry_module_id: int | None = Query(default=None, description="按入口模块ID过滤"), + type_ids: str | None = Query(default=None, description="按文档类型ID列表过滤,逗号分隔"), + document_type_id: int | None = Query(default=None, description="按单个文档类型ID过滤"), status: str | None = Query(default=None), resultStatus: str | None = Query(default=None), createdBy: int | None = Query(default=None), @@ -72,6 +83,18 @@ class GovdocController(BaseController): 后端自动附加 engine_type='govdoc' 过滤条件。 """ + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "govdoc:document:read"): + return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看公文列表权限", "data": None}) + typeIdList: list[int] = [] + if type_ids: + typeIdList = [ + int(item.strip()) + for item in type_ids.split(",") + if item.strip().isdigit() and int(item.strip()) > 0 + ] + if document_type_id is not None and document_type_id > 0: + typeIdList.append(document_type_id) + result = await self.GovdocService.ListDocuments( page=page, pageSize=pageSize, @@ -79,6 +102,8 @@ class GovdocController(BaseController): fileExt=fileExt, region=region, tenantCode=tenant_code, + entryModuleId=entry_module_id, + typeIds=typeIdList or None, status=status, resultStatus=resultStatus, createdBy=createdBy, diff --git a/fastapi_modules/fastapi_leaudit/controllers/homeController.py b/fastapi_modules/fastapi_leaudit/controllers/homeController.py index 4b1ef42..4a2fe0b 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/homeController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/homeController.py @@ -2,13 +2,13 @@ from typing import Any -from fastapi import Depends +from fastapi import Depends, Query from fastapi_common.fastapi_common_security.security import verify_access_token from fastapi_common.fastapi_common_web.controller import BaseController from fastapi_common.fastapi_common_web.domain.responses import Result -from fastapi_modules.fastapi_leaudit.domian.vo.homeVo import HomeEntryModuleVO +from fastapi_modules.fastapi_leaudit.domian.vo.homeVo import HomeDashboardStatisticsVO, HomeEntryModuleVO from fastapi_modules.fastapi_leaudit.services import IHomeService from fastapi_modules.fastapi_leaudit.services.impl.homeServiceImpl import HomeServiceImpl @@ -25,3 +25,24 @@ class HomeController(BaseController): """获取当前用户可见的首页入口模块。""" Data = await self.HomeService.GetEntryModules(UserId=int(payload["user_id"])) return Result.success(data=Data) + + @self.router.get("/statistics/dashboard", response_model=Result[HomeDashboardStatisticsVO]) + async def GetDashboardStatistics( + today: str | None = Query(None, description="统计基准日期,格式 YYYY-MM-DD"), + type_ids: str | None = Query(None, description="文档类型ID,逗号分隔"), + entry_module_id: int | None = Query(None, description="入口模块ID"), + payload: dict[str, Any] = Depends(verify_access_token), + ): + """获取首页统计卡片数据。""" + typeIds = [ + int(item) + for item in str(type_ids or "").split(",") + if item.strip().isdigit() and int(item.strip()) > 0 + ] + Data = await self.HomeService.GetDashboardStatistics( + UserId=int(payload["user_id"]), + Today=today, + TypeIds=typeIds, + EntryModuleId=entry_module_id, + ) + return Result.success(data=Data) diff --git a/fastapi_modules/fastapi_leaudit/controllers/qichachaController.py b/fastapi_modules/fastapi_leaudit/controllers/qichachaController.py new file mode 100644 index 0000000..d2fe306 --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/controllers/qichachaController.py @@ -0,0 +1,99 @@ +"""企查查控制器。""" + +from typing import Any + +from fastapi import Depends, Query +from fastapi.responses import JSONResponse + +from fastapi_common.fastapi_common_security.security import verify_access_token +from fastapi_common.fastapi_common_web.controller import BaseController +from fastapi_common.fastapi_common_web.domain.responses import Result +from fastapi_modules.fastapi_leaudit.domian.Dto.qichachaDto import QichachaBatchQueryDTO, QichachaCompanyQueryDTO +from fastapi_modules.fastapi_leaudit.domian.vo.qichachaVo import ( + QichachaBatchQueryVO, + QichachaCompanyQueryVO, + QichachaRecordStatusVO, +) +from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl +from fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl import QichachaServiceImpl +from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService +from fastapi_modules.fastapi_leaudit.services.qichachaService import IQichachaService + + +class QichachaController(BaseController): + """企查查控制器。""" + + def __init__(self): + super().__init__(prefix="/v2/qichacha", tags=["企查查"]) + self.QichachaService: IQichachaService = QichachaServiceImpl() + self.PermissionService: IPermissionService = PermissionServiceImpl() + + @self.router.post("/company", response_model=Result[QichachaCompanyQueryVO]) + async def QueryCompany(Body: QichachaCompanyQueryDTO, payload: dict[str, Any] = Depends(verify_access_token)): + """查询企业完整信息。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "qichacha:company:query"): + return JSONResponse( + status_code=403, + content={"code": 403, "message": "当前用户没有查询企业信息权限", "data": None}, + ) + data = await self.QichachaService.QueryCompany( + Keyword=Body.keyword, + ForceRefresh=Body.forceRefresh, + ) + return Result.success(data=data) + + @self.router.post("/enterprise", response_model=Result[QichachaCompanyQueryVO]) + async def QueryEnterprise(Body: QichachaCompanyQueryDTO, payload: dict[str, Any] = Depends(verify_access_token)): + """仅查询企业工商信息。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "qichacha:company:query"): + return JSONResponse( + status_code=403, + content={"code": 403, "message": "当前用户没有查询企业信息权限", "data": None}, + ) + data = await self.QichachaService.QueryEnterpriseOnly( + Keyword=Body.keyword, + ForceRefresh=Body.forceRefresh, + ) + return Result.success(data=data) + + @self.router.post("/dishonesty", response_model=Result[QichachaCompanyQueryVO]) + async def QueryDishonesty(Body: QichachaCompanyQueryDTO, payload: dict[str, Any] = Depends(verify_access_token)): + """仅查询企业失信信息。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "qichacha:company:query"): + return JSONResponse( + status_code=403, + content={"code": 403, "message": "当前用户没有查询企业信息权限", "data": None}, + ) + data = await self.QichachaService.QueryDishonestyOnly( + Keyword=Body.keyword, + ForceRefresh=Body.forceRefresh, + ) + return Result.success(data=data) + + @self.router.post("/batch", response_model=Result[QichachaBatchQueryVO]) + async def BatchQuery(Body: QichachaBatchQueryDTO, payload: dict[str, Any] = Depends(verify_access_token)): + """批量查询企业信息。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "qichacha:company:query"): + return JSONResponse( + status_code=403, + content={"code": 403, "message": "当前用户没有查询企业信息权限", "data": None}, + ) + data = await self.QichachaService.BatchQuery( + Keywords=Body.keywords, + ForceRefresh=Body.forceRefresh, + ) + return Result.success(data=data) + + @self.router.get("/status", response_model=Result[QichachaRecordStatusVO]) + async def GetRecordStatus( + keyword: str = Query(..., min_length=2, description="企业名称或统一社会信用代码"), + payload: dict[str, Any] = Depends(verify_access_token), + ): + """查询企业缓存状态。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "qichacha:status:read"): + return JSONResponse( + status_code=403, + content={"code": 403, "message": "当前用户没有查看企业缓存状态权限", "data": None}, + ) + data = await self.QichachaService.GetRecordStatus(Keyword=keyword) + return Result.success(data=data) diff --git a/fastapi_modules/fastapi_leaudit/controllers/usageStatsController.py b/fastapi_modules/fastapi_leaudit/controllers/usageStatsController.py index 0a832db..0b7e9f6 100644 --- a/fastapi_modules/fastapi_leaudit/controllers/usageStatsController.py +++ b/fastapi_modules/fastapi_leaudit/controllers/usageStatsController.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import Any from fastapi import Depends, Query +from fastapi.responses import JSONResponse from fastapi_common.fastapi_common_security.security import verify_access_token from fastapi_common.fastapi_common_web.controller import BaseController @@ -18,7 +19,9 @@ from fastapi_modules.fastapi_leaudit.domian.vo.usageStatsVo import ( UsageStatsTrendVO, UsageStatsUserPageVO, ) +from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl from fastapi_modules.fastapi_leaudit.services.impl.usageStatsServiceImpl import UsageStatsServiceImpl +from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService from fastapi_modules.fastapi_leaudit.services.usageStatsService import IUsageStatsService @@ -28,6 +31,7 @@ class UsageStatsController(BaseController): def __init__(self): super().__init__(prefix="/v3/usage-stats", tags=["系统使用统计"]) self.UsageStatsService: IUsageStatsService = UsageStatsServiceImpl() + self.PermissionService: IPermissionService = PermissionServiceImpl() @self.router.get("/overview", response_model=Result[UsageStatsOverviewVO]) async def GetOverview( @@ -39,6 +43,9 @@ class UsageStatsController(BaseController): documentTypeId: int | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """查询系统使用统计总览。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:overview:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看统计总览权限", "data": None}) data = await self.UsageStatsService.GetOverview( CurrentUserId=int(payload["user_id"]), Filters={ @@ -64,6 +71,9 @@ class UsageStatsController(BaseController): documentTypeId: int | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """查询系统使用统计趋势。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:trends:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看统计趋势权限", "data": None}) data = await self.UsageStatsService.GetTrends( CurrentUserId=int(payload["user_id"]), Filters={ @@ -92,6 +102,9 @@ class UsageStatsController(BaseController): dateTo: str | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """按用户维度查询系统使用统计。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:users:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看用户统计权限", "data": None}) data = await self.UsageStatsService.GetUsers( CurrentUserId=int(payload["user_id"]), Filters={ @@ -119,6 +132,9 @@ class UsageStatsController(BaseController): dateTo: str | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """按部门维度查询系统使用统计。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:departments:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看部门统计权限", "data": None}) data = await self.UsageStatsService.GetDepartments( CurrentUserId=int(payload["user_id"]), Filters={ @@ -144,6 +160,9 @@ class UsageStatsController(BaseController): documentTypeId: int | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """按地区维度查询系统使用统计。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:areas:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看地区统计权限", "data": None}) data = await self.UsageStatsService.GetAreas( CurrentUserId=int(payload["user_id"]), Filters={ @@ -173,6 +192,9 @@ class UsageStatsController(BaseController): dateTo: str | None = None, payload: dict[str, Any] = Depends(verify_access_token), ): + """查询系统使用统计明细。""" + if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "usage_stats:details:read"): + return JSONResponse(status_code=403, content={"code": 403, "message": "当前用户没有查看统计明细权限", "data": None}) data = await self.UsageStatsService.GetDetails( CurrentUserId=int(payload["user_id"]), Filters={ diff --git a/fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py b/fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py index 1452dba..9d83a4d 100644 --- a/fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py +++ b/fastapi_modules/fastapi_leaudit/domian/Dto/entryModuleDto.py @@ -27,6 +27,8 @@ class EntryModuleCreateDTO(BaseModel): description: str | None = Field(None, description="模块描述") path: str | None = Field(None, description="前端路由路径") route_path: str | None = Field(None, description="前端跳转路径") + menu_profile: str | None = Field(None, description="菜单模板:document_review/contract/govdoc/custom") + features: list[str] | None = Field(None, description="启用功能编码列表") areas: list[EntryModuleAreaDTO] | None = Field(None, description="历史地区配置(兼容字段,建议改用 tenants)") tenants: list[EntryModuleTenantDTO] | None = Field(None, description="租户配置") @@ -38,5 +40,7 @@ class EntryModuleUpdateDTO(BaseModel): description: str | None = Field(None, description="模块描述") path: str | None = Field(None, description="前端路由路径") route_path: str | None = Field(None, description="前端跳转路径") + menu_profile: str | None = Field(None, description="菜单模板:document_review/contract/govdoc/custom") + features: list[str] | None = Field(None, description="启用功能编码列表") areas: list[EntryModuleAreaDTO] | None = Field(None, description="历史地区配置(兼容字段,建议改用 tenants)") tenants: list[EntryModuleTenantDTO] | None = Field(None, description="租户配置") diff --git a/fastapi_modules/fastapi_leaudit/domian/Dto/qichachaDto.py b/fastapi_modules/fastapi_leaudit/domian/Dto/qichachaDto.py new file mode 100644 index 0000000..4b4ef7e --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/domian/Dto/qichachaDto.py @@ -0,0 +1,17 @@ +"""企查查 DTO。""" + +from pydantic import BaseModel, Field + + +class QichachaCompanyQueryDTO(BaseModel): + """企业查询请求。""" + + keyword: str = Field(..., min_length=2, max_length=200, description="企业名称或统一社会信用代码") + forceRefresh: bool = Field(False, description="是否强制刷新缓存") + + +class QichachaBatchQueryDTO(BaseModel): + """批量企业查询请求。""" + + keywords: list[str] = Field(..., min_length=1, max_length=10, description="企业名称或统一社会信用代码列表") + forceRefresh: bool = Field(False, description="是否强制刷新缓存") diff --git a/fastapi_modules/fastapi_leaudit/domian/vo/crossReviewVo.py b/fastapi_modules/fastapi_leaudit/domian/vo/crossReviewVo.py index 63c5374..eb53f7e 100644 --- a/fastapi_modules/fastapi_leaudit/domian/vo/crossReviewVo.py +++ b/fastapi_modules/fastapi_leaudit/domian/vo/crossReviewVo.py @@ -23,12 +23,14 @@ class CrossReviewTaskItemVO(BaseModel): docTypeId: int | None = Field(None, description="文档类型ID") docTypeCode: str | None = Field(None, description="文档类型编码") status: str = Field(..., description="任务状态") - progress: float = Field(0, description="进度百分比") - totalDocuments: int = Field(0, description="文档总数") - completedDocuments: int = Field(0, description="已完成文档数") + progress: float | None = Field(0, description="进度百分比") + totalDocuments: int | None = Field(0, description="文档总数") + completedDocuments: int | None = Field(0, description="已完成文档数") createdAt: datetime | None = Field(None, description="创建时间") evaluationTenants: list[CrossReviewTaskTenantVO] = Field(default_factory=list, description="评查租户列表") evaluationRegion: list[str] = Field(default_factory=list, description="评查租户/地区(兼容展示值)") + currentUserRole: str = Field("participant", description="当前用户在任务中的角色:assigner/principal/participant") + currentUserCanConfirm: bool = Field(False, description="当前用户是否可确认完成任务文档") class CrossReviewTaskPageVO(BaseModel): diff --git a/fastapi_modules/fastapi_leaudit/domian/vo/documentVo.py b/fastapi_modules/fastapi_leaudit/domian/vo/documentVo.py index 0ff0da6..04e6ade 100644 --- a/fastapi_modules/fastapi_leaudit/domian/vo/documentVo.py +++ b/fastapi_modules/fastapi_leaudit/domian/vo/documentVo.py @@ -20,6 +20,7 @@ class DocumentUploadVO(BaseModel): typeId: int = Field(..., description="文档类型ID") typeCode: str = Field(..., description="文档类型编码") groupId: int | None = Field(None, description="命中的二级分组ID") + entryModuleId: int | None = Field(None, description="所属入口模块ID") region: str = Field(..., description="所属地区") tenantCode: str | None = Field(None, description="所属租户编码") tenantName: str | None = Field(None, description="所属租户名称") @@ -109,6 +110,7 @@ class DocumentListItemVO(BaseModel): typeName: str | None = Field(None, description="文档类型名称") groupId: int | None = Field(None, description="命中的二级分组ID") groupName: str | None = Field(None, description="二级分组名称") + entryModuleId: int | None = Field(None, description="所属入口模块ID") region: str = Field(..., description="区域") tenantCode: str | None = Field(None, description="所属租户编码") tenantName: str | None = Field(None, description="所属租户名称") diff --git a/fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py b/fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py index d025356..bc34219 100644 --- a/fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py +++ b/fastapi_modules/fastapi_leaudit/domian/vo/entryModuleAdminVo.py @@ -12,6 +12,14 @@ class EntryModuleTenantVO(BaseModel): sort_order: int = Field(0, description="排序号") +class EntryModuleBusinessScopeVO(BaseModel): + """入口模块业务范围摘要。""" + + category_count: int = Field(0, description="业务大类数量") + business_type_count: int = Field(0, description="业务类型数量") + categories: list[str] = Field(default_factory=list, description="业务大类名称列表") + + class EntryModuleVO(BaseModel): """入口模块详情。""" @@ -20,9 +28,12 @@ class EntryModuleVO(BaseModel): description: str | None = Field(None, description="模块描述") path: str | None = Field(None, description="图标路径") route_path: str | None = Field(None, description="前端跳转路径") + menu_profile: str = Field("document_review", description="菜单模板") + features: list[str] = Field(default_factory=list, description="启用功能编码列表") sort_order: int = Field(0, description="排序") is_enabled: bool = Field(True, description="是否启用") tenants: list[EntryModuleTenantVO] = Field(default_factory=list, description="租户配置") + business_scope: EntryModuleBusinessScopeVO = Field(default_factory=EntryModuleBusinessScopeVO, description="业务范围摘要") created_at: str | None = Field(None, description="创建时间") updated_at: str | None = Field(None, description="更新时间") diff --git a/fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py b/fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py index cdc6069..441c1d0 100644 --- a/fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py +++ b/fastapi_modules/fastapi_leaudit/domian/vo/homeVo.py @@ -36,9 +36,31 @@ class HomeEntryModuleVO(BaseModel): description: str | None = Field(None, description="模块描述") targetPath: str | None = Field(None, description="点击后跳转路径") routePath: str | None = Field(None, description="用于 RBAC 校验的页面路径") + menuProfile: str = Field("document_review", description="菜单模板") + features: list[str] = Field(default_factory=list, description="启用功能编码列表") + tenantCode: str | None = Field(None, description="当前命中的租户编码") iconPath: str | None = Field(None, description="模块图标路径") sortOrder: int = Field(0, description="排序序号") requiresDocumentTypes: bool = Field(True, description="是否要求至少绑定一个文档类型") areas: list[HomeEntryAreaVO] = Field(default_factory=list, description="地区配置") tenants: list[HomeEntryTenantVO] = Field(default_factory=list, description="租户配置") documentTypes: list[HomeEntryDocumentTypeVO] = Field(default_factory=list, description="关联文档类型列表") + + +class HomeDashboardGrowthVO(BaseModel): + """首页统计环比数据。""" + + value: int = Field(0, description="环比百分比") + isUp: bool = Field(True, description="是否上升") + + +class HomeDashboardStatisticsVO(BaseModel): + """首页统计卡片数据。""" + + todayPendingFiles: int = Field(0, description="今日待审文件数") + monthlyReviewedFiles: int = Field(0, description="本月已审核文件数") + monthlyReviewGrowth: HomeDashboardGrowthVO = Field(default_factory=HomeDashboardGrowthVO, description="本月审核数环比") + monthlyPassRate: int = Field(0, description="本月审核通过率") + passRateGrowth: HomeDashboardGrowthVO = Field(default_factory=HomeDashboardGrowthVO, description="通过率环比") + issuesDetected: int = Field(0, description="本月问题检出数") + issuesGrowth: HomeDashboardGrowthVO = Field(default_factory=HomeDashboardGrowthVO, description="问题检出数环比") diff --git a/fastapi_modules/fastapi_leaudit/domian/vo/qichachaVo.py b/fastapi_modules/fastapi_leaudit/domian/vo/qichachaVo.py new file mode 100644 index 0000000..a97483b --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/domian/vo/qichachaVo.py @@ -0,0 +1,55 @@ +"""企查查 VO。""" + +from __future__ import annotations + +from typing import Any + +from pydantic import BaseModel, Field + + +class QichachaCompanyInfoVO(BaseModel): + """企业信息响应。""" + + searchKey: str = Field(..., description="查询关键词") + creditCode: str | None = Field(None, description="统一社会信用代码") + companyName: str | None = Field(None, description="企业名称") + enterprise: dict[str, Any] | None = Field(None, description="工商信息") + dishonesty: dict[str, Any] | None = Field(None, description="失信信息") + hasDishonesty: bool = Field(False, description="是否存在失信记录") + dishonestyCount: int = Field(0, description="失信记录数量") + updatedAt: str | None = Field(None, description="更新时间") + + +class QichachaCompanyQueryVO(BaseModel): + """企业查询响应。""" + + success: bool = Field(..., description="是否成功") + message: str = Field(..., description="响应消息") + data: QichachaCompanyInfoVO | None = Field(None, description="企业信息") + errorCode: str | None = Field(None, description="错误码") + errorDetails: dict[str, Any] | None = Field(None, description="错误详情") + + +class QichachaBatchQueryVO(BaseModel): + """批量企业查询响应。""" + + success: bool = Field(..., description="是否全部成功") + total: int = Field(..., description="查询总数") + successCount: int = Field(..., description="成功数") + failedCount: int = Field(..., description="失败数") + results: list[QichachaCompanyQueryVO] = Field(default_factory=list, description="查询结果") + + +class QichachaRecordStatusVO(BaseModel): + """企业缓存记录状态响应。""" + + exists: bool = Field(..., description="是否存在缓存") + searchKey: str = Field(..., description="查询关键词") + creditCode: str | None = Field(None, description="统一社会信用代码") + companyName: str | None = Field(None, description="企业名称") + hasEnterprise: bool = Field(False, description="是否有工商信息") + hasDishonesty: bool = Field(False, description="是否有失信信息") + updatedAt: str | None = Field(None, description="更新时间") + ageDays: int | None = Field(None, description="缓存天数") + refreshThresholdDays: int = Field(..., description="刷新阈值") + needRefresh: bool = Field(False, description="是否需要刷新") diff --git a/fastapi_modules/fastapi_leaudit/models/__init__.py b/fastapi_modules/fastapi_leaudit/models/__init__.py index 800adcb..8369163 100644 --- a/fastapi_modules/fastapi_leaudit/models/__init__.py +++ b/fastapi_modules/fastapi_leaudit/models/__init__.py @@ -17,6 +17,7 @@ from fastapi_modules.fastapi_leaudit.models.usageLoginEvent import UsageLoginEve from fastapi_modules.fastapi_leaudit.models.govdocRun import GovdocRun from fastapi_modules.fastapi_leaudit.models.govdocRuleResult import GovdocRuleResult from fastapi_modules.fastapi_leaudit.models.govdocReportArtifact import GovdocReportArtifact +from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo __all__ = [ "LeauditDocument", @@ -36,4 +37,5 @@ __all__ = [ "GovdocRun", "GovdocRuleResult", "GovdocReportArtifact", + "QichachaCompanyInfo", ] diff --git a/fastapi_modules/fastapi_leaudit/models/qichachaCompanyInfo.py b/fastapi_modules/fastapi_leaudit/models/qichachaCompanyInfo.py new file mode 100644 index 0000000..a055906 --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/models/qichachaCompanyInfo.py @@ -0,0 +1,84 @@ +"""企查查企业信息缓存模型。""" + +from __future__ import annotations + +from datetime import UTC, datetime +from typing import Any + +from sqlalchemy import BigInteger, Index, String, or_, select +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import Mapped, mapped_column + +from fastapi_common.fastapi_common_web.models import BaseModel + + +class QichachaCompanyInfo(BaseModel): + """企查查企业信息缓存表。""" + + __tablename__ = "qcc_company_info" + __table_args__ = ( + Index("idx_qcc_company_search_key", "search_key", unique=True), + Index("idx_qcc_company_credit_code", "credit_code"), + Index("idx_qcc_company_name", "company_name"), + ) + + Id: Mapped[int] = mapped_column("id", BigInteger, primary_key=True, autoincrement=True) + searchKey: Mapped[str] = mapped_column("search_key", String(200), nullable=False, comment="查询关键词") + creditCode: Mapped[str | None] = mapped_column("credit_code", String(64), comment="统一社会信用代码") + companyName: Mapped[str | None] = mapped_column("company_name", String(255), comment="企业名称") + enterprise: Mapped[dict[str, Any] | None] = mapped_column("enterprise", JSONB, comment="工商信息") + dishonesty: Mapped[dict[str, Any] | None] = mapped_column("dishonesty", JSONB, comment="失信信息") + + @classmethod + async def FindByKeyword(cls, session: AsyncSession, Keyword: str) -> "QichachaCompanyInfo | None": + """按查询词、信用代码或企业名查询缓存。""" + return await session.scalar( + select(cls).where( + cls.deleted_at.is_(None), + or_( + cls.searchKey == Keyword, + cls.creditCode == Keyword, + cls.companyName == Keyword, + ), + ) + ) + + @classmethod + async def Upsert( + cls, + session: AsyncSession, + SearchKey: str, + CreditCode: str | None, + CompanyName: str | None, + Enterprise: dict[str, Any] | None, + Dishonesty: dict[str, Any] | None, + ) -> "QichachaCompanyInfo": + """按查询关键词写入或更新缓存。""" + record = await cls.FindByKeyword(session, SearchKey) + if record is None: + record = cls( + searchKey=SearchKey, + creditCode=CreditCode, + companyName=CompanyName, + enterprise=Enterprise, + dishonesty=Dishonesty, + ) + session.add(record) + else: + record.searchKey = SearchKey + record.creditCode = CreditCode + record.companyName = CompanyName + record.enterprise = Enterprise + record.dishonesty = Dishonesty + record.updated_at = datetime.now(UTC) + await session.flush() + return record + + @classmethod + def GetAgeDays(cls, record: "QichachaCompanyInfo") -> int: + """计算缓存记录距今天数。""" + updated_at = record.updated_at + if updated_at.tzinfo is None: + updated_at = updated_at.replace(tzinfo=UTC) + return max((datetime.now(UTC) - updated_at).days, 0) diff --git a/fastapi_modules/fastapi_leaudit/services/__init__.py b/fastapi_modules/fastapi_leaudit/services/__init__.py index efedcef..067f8d2 100644 --- a/fastapi_modules/fastapi_leaudit/services/__init__.py +++ b/fastapi_modules/fastapi_leaudit/services/__init__.py @@ -20,6 +20,7 @@ from fastapi_modules.fastapi_leaudit.services.ragChatService import IRagChatServ from fastapi_modules.fastapi_leaudit.services.tenantService import ITenantService from fastapi_modules.fastapi_leaudit.services.govdocService import IGovdocService from fastapi_modules.fastapi_leaudit.services.usageStatsService import IUsageStatsService +from fastapi_modules.fastapi_leaudit.services.qichachaService import IQichachaService __all__ = [ "IAuditService", @@ -42,4 +43,5 @@ __all__ = [ "ITenantService", "IUsageStatsService", "IGovdocService", + "IQichachaService", ] diff --git a/fastapi_modules/fastapi_leaudit/services/crossReviewService.py b/fastapi_modules/fastapi_leaudit/services/crossReviewService.py index dbea998..84d9c20 100644 --- a/fastapi_modules/fastapi_leaudit/services/crossReviewService.py +++ b/fastapi_modules/fastapi_leaudit/services/crossReviewService.py @@ -35,7 +35,12 @@ class ICrossReviewService(ABC): ... @abstractmethod - async def GetUserTasks(self, CurrentUserId: int, Body: CrossReviewTaskQueryDTO) -> CrossReviewTaskPageVO: + async def GetUserTasks( + self, + CurrentUserId: int, + Body: CrossReviewTaskQueryDTO, + CanViewProgress: bool = True, + ) -> CrossReviewTaskPageVO: """查询当前用户参与的交叉评查任务。""" ... diff --git a/fastapi_modules/fastapi_leaudit/services/documentService.py b/fastapi_modules/fastapi_leaudit/services/documentService.py index 6605508..fccdbd5 100644 --- a/fastapi_modules/fastapi_leaudit/services/documentService.py +++ b/fastapi_modules/fastapi_leaudit/services/documentService.py @@ -81,6 +81,11 @@ class IDocumentService(ABC): """获取评查详情页所需的聚合数据。""" ... + @abstractmethod + async def IsCrossReviewDocument(self, DocumentId: int) -> bool: + """判断文档是否属于交叉评查范围。""" + ... + @abstractmethod async def AuditReviewPoint( self, diff --git a/fastapi_modules/fastapi_leaudit/services/evaluationPointGroupService.py b/fastapi_modules/fastapi_leaudit/services/evaluationPointGroupService.py index db7f978..9419566 100755 --- a/fastapi_modules/fastapi_leaudit/services/evaluationPointGroupService.py +++ b/fastapi_modules/fastapi_leaudit/services/evaluationPointGroupService.py @@ -36,11 +36,18 @@ class IEvaluationPointGroupService(ABC): Page: int, PageSize: int, CurrentUserId: int, + EntryModuleId: int | None = None, ) -> EvaluationPointGroupListVO: ... @abstractmethod - async def ListAllGroups(self, IncludeDisabled: bool, WithRuleCount: bool, CurrentUserId: int) -> list[EvaluationPointGroupVO]: + async def ListAllGroups( + self, + IncludeDisabled: bool, + WithRuleCount: bool, + CurrentUserId: int, + EntryModuleId: int | None = None, + ) -> list[EvaluationPointGroupVO]: ... @abstractmethod diff --git a/fastapi_modules/fastapi_leaudit/services/govdocService.py b/fastapi_modules/fastapi_leaudit/services/govdocService.py index dbccd66..8f8e3c8 100644 --- a/fastapi_modules/fastapi_leaudit/services/govdocService.py +++ b/fastapi_modules/fastapi_leaudit/services/govdocService.py @@ -16,6 +16,7 @@ class IGovdocService(ABC): self, file: UploadFile, typeId: int | None = None, + entryModuleId: int | None = None, region: str | None = None, tenantCode: str | None = None, autoRun: bool = False, @@ -35,6 +36,8 @@ class IGovdocService(ABC): fileExt: str | None = None, region: str | None = None, tenantCode: str | None = None, + entryModuleId: int | None = None, + typeIds: list[int] | None = None, status: str | None = None, resultStatus: str | None = None, createdBy: int | None = None, diff --git a/fastapi_modules/fastapi_leaudit/services/homeService.py b/fastapi_modules/fastapi_leaudit/services/homeService.py index 6849c44..e138e67 100644 --- a/fastapi_modules/fastapi_leaudit/services/homeService.py +++ b/fastapi_modules/fastapi_leaudit/services/homeService.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod -from fastapi_modules.fastapi_leaudit.domian.vo.homeVo import HomeEntryModuleVO +from fastapi_modules.fastapi_leaudit.domian.vo.homeVo import HomeDashboardStatisticsVO, HomeEntryModuleVO class IHomeService(ABC): @@ -12,3 +12,14 @@ class IHomeService(ABC): async def GetEntryModules(self, UserId: int) -> list[HomeEntryModuleVO]: """获取当前用户可见的首页入口模块。""" ... + + @abstractmethod + async def GetDashboardStatistics( + self, + UserId: int, + Today: str | None = None, + TypeIds: list[int] | None = None, + EntryModuleId: int | None = None, + ) -> HomeDashboardStatisticsVO: + """获取当前业务入口的首页统计卡片数据。""" + ... diff --git a/fastapi_modules/fastapi_leaudit/services/impl/crossReviewServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/crossReviewServiceImpl.py index f4c41c0..9ed3326 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/crossReviewServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/crossReviewServiceImpl.py @@ -200,7 +200,7 @@ class CrossReviewServiceImpl(ICrossReviewService): await self._ensure_tables_ready(session) memberUserIds = self._unique_int_list(Body.memberUserIds + [CurrentUserId]) - principalUserIds = self._unique_int_list(Body.principalUserIds) + principalUserIds = self._unique_int_list(Body.principalUserIds + [CurrentUserId]) documentIds = self._unique_int_list(Body.documentIds) await self._assert_task_scope_inputs(session, CurrentUserId, memberUserIds, documentIds) @@ -289,7 +289,12 @@ class CrossReviewServiceImpl(ICrossReviewService): documentCount=len(documentIds), ) - async def GetUserTasks(self, CurrentUserId: int, Body: CrossReviewTaskQueryDTO) -> CrossReviewTaskPageVO: + async def GetUserTasks( + self, + CurrentUserId: int, + Body: CrossReviewTaskQueryDTO, + CanViewProgress: bool = True, + ) -> CrossReviewTaskPageVO: """查询当前用户参与的交叉评查任务。""" async with GetAsyncSession() as session: await self._ensure_tables_ready(session) @@ -401,6 +406,15 @@ class CrossReviewServiceImpl(ICrossReviewService): t.doc_type_code, t.status, t.create_time, + CASE + WHEN t.assigner_id = :current_user_id THEN 'assigner' + ELSE COALESCE(MAX(tm.member_role), 'participant') + END AS current_user_role, + CASE + WHEN t.assigner_id = :current_user_id THEN TRUE + WHEN COALESCE(MAX(CASE WHEN tm.member_role = 'principal' THEN 1 ELSE 0 END), 0) = 1 THEN TRUE + ELSE FALSE + END AS current_user_can_confirm, COALESCE(ds.total_documents, 0) AS total_documents, COALESCE(ds.completed_documents, 0) AS completed_documents, COALESCE(tt.evaluation_tenants, '[]'::jsonb) AS evaluation_tenants, @@ -416,7 +430,7 @@ class CrossReviewServiceImpl(ICrossReviewService): ON tr.task_id = t.id WHERE {whereSql} GROUP BY - t.id, t.task_name, t.task_type, t.doc_type_id, t.doc_type_code, + t.id, t.task_name, t.task_type, t.doc_type_id, t.doc_type_code, t.assigner_id, t.status, t.create_time, ds.total_documents, ds.completed_documents, tt.evaluation_tenants, tr.evaluation_regions ORDER BY t.create_time DESC, t.id DESC @@ -429,35 +443,7 @@ class CrossReviewServiceImpl(ICrossReviewService): items = [] for row in rows: - totalDocuments = int(row["total_documents"] or 0) - completedDocuments = int(row["completed_documents"] or 0) - progress = round((completedDocuments / totalDocuments * 100) if totalDocuments > 0 else 0, 2) - evaluationTenants = self._parse_task_tenants(row.get("evaluation_tenants")) - rawRegions = row.get("evaluation_regions") - if rawRegions is None: - evaluationRegion: list[str] = [] - elif isinstance(rawRegions, list): - evaluationRegion = [str(r) for r in rawRegions] - else: - evaluationRegion = [str(rawRegions)] - if not evaluationRegion: - evaluationRegion = [tenant.tenantName for tenant in evaluationTenants if tenant.tenantName] - items.append( - CrossReviewTaskItemVO( - taskId=int(row["task_id"]), - taskName=str(row["task_name"]), - taskType=str(row["task_type"]), - docTypeId=self._to_int(row.get("doc_type_id")), - docTypeCode=row.get("doc_type_code"), - status=str(row["status"]), - progress=progress, - totalDocuments=totalDocuments, - completedDocuments=completedDocuments, - createdAt=row.get("create_time"), - evaluationTenants=evaluationTenants, - evaluationRegion=evaluationRegion, - ) - ) + items.append(self._build_task_item_vo(row=row, CanViewProgress=CanViewProgress)) return CrossReviewTaskPageVO(total=total, page=Body.page, pageSize=Body.pageSize, items=items) @@ -518,7 +504,32 @@ class CrossReviewServiceImpl(ICrossReviewService): baseWhereClauses.append("(d.normalized_name ILIKE :keyword OR CAST(d.biz_document_id AS TEXT) ILIKE :keyword)") params["keyword"] = f"%{Body.keyword.strip()}%" baseWhereSql = " AND ".join(baseWhereClauses) - latestWhereSql = f"{baseWhereSql} AND COALESCE(d.is_latest_version, false) = true" + taskDocumentsSql = f""" + SELECT + td.task_id, + td.document_id, + td.audit_status, + d.id, + d.normalized_name, + d.biz_document_id, + d.type_id, + d.processing_status, + d.version_no, + d.is_latest_version, + d.version_group_key, + d.root_version_id, + d.current_run_id, + d.created_at, + COALESCE(NULLIF(d.version_group_key, ''), CONCAT('root:', COALESCE(d.root_version_id, d.id)::text)) AS task_version_group_key, + ROW_NUMBER() OVER ( + PARTITION BY COALESCE(NULLIF(d.version_group_key, ''), CONCAT('root:', COALESCE(d.root_version_id, d.id)::text)) + ORDER BY d.version_no DESC, d.id DESC + ) AS task_version_rank + FROM leaudit_cross_review_task_documents td + JOIN leaudit_documents d + ON d.id = td.document_id + WHERE {baseWhereSql} + """ total = int( ( @@ -526,10 +537,8 @@ class CrossReviewServiceImpl(ICrossReviewService): text( f""" SELECT COUNT(*) - FROM leaudit_cross_review_task_documents td - JOIN leaudit_documents d - ON d.id = td.document_id - WHERE {latestWhereSql} + FROM ({taskDocumentsSql}) task_docs + WHERE task_docs.task_version_rank = 1 """ ), params, @@ -558,10 +567,10 @@ class CrossReviewServiceImpl(ICrossReviewService): ) AS processing_status, d.version_no, d.is_latest_version, - COALESCE(NULLIF(d.version_group_key, ''), CONCAT('root:', COALESCE(d.root_version_id, d.id)::text)) AS version_group_key, + d.task_version_group_key AS version_group_key, COALESCE(vc.total_versions, 1)::int AS total_versions, d.created_at, - td.audit_status, + d.audit_status, COALESCE(dt.name, '') AS type_name, COALESCE(df.file_size, 0) AS file_size, COALESCE(df.file_path, '') AS path, @@ -581,9 +590,7 @@ class CrossReviewServiceImpl(ICrossReviewService): COALESCE(es.full_score, 0) AS full_score, COALESCE(es.score_summary, '') AS score_summary, COALESCE(es.score_percent, 0) AS score_percent - FROM leaudit_cross_review_task_documents td - JOIN leaudit_documents d - ON d.id = td.document_id + FROM ({taskDocumentsSql}) d LEFT JOIN leaudit_audit_runs ar ON ar.id = d.current_run_id LEFT JOIN leaudit_document_types dt @@ -608,7 +615,7 @@ class CrossReviewServiceImpl(ICrossReviewService): WHERE d2.deleted_at IS NULL GROUP BY d2.version_group_key , COALESCE(d2.root_version_id, d2.id) - ) vc ON vc.version_group_key = COALESCE(NULLIF(d.version_group_key, ''), CONCAT('root:', COALESCE(d.root_version_id, d.id)::text)) + ) vc ON vc.version_group_key = d.task_version_group_key LEFT JOIN LATERAL ( SELECT COUNT(*)::int AS total_evaluation_points, @@ -661,7 +668,7 @@ class CrossReviewServiceImpl(ICrossReviewService): AND p.status = 'approved' AND p.delete_time IS NULL ) pd ON TRUE - WHERE {latestWhereSql} + WHERE d.task_version_rank = 1 ORDER BY d.created_at DESC, d.id DESC LIMIT :limit OFFSET :offset """ @@ -2099,13 +2106,15 @@ class CrossReviewServiceImpl(ICrossReviewService): if not member_tenant_code and not member_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_400_BAD_REQUEST, f"成员用户未绑定有效租户: {user_id}") resolved_scopes.append({"tenant_code": member_tenant_code, "tenant_name": member_tenant_name}) + if is_global: + continue if current_tenant_code: if member_tenant_code: if member_tenant_code != current_tenant_code: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户用户加入交叉评查任务: {user_id}") elif member_tenant_name != current_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户用户加入交叉评查任务: {user_id}") - elif not is_global and member_tenant_name != current_tenant_name: + elif member_tenant_name != current_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户用户加入交叉评查任务: {user_id}") if document_ids: @@ -2141,13 +2150,15 @@ class CrossReviewServiceImpl(ICrossReviewService): if not document_tenant_code and not document_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_400_BAD_REQUEST, f"任务文档未绑定有效租户: {document_id}") resolved_scopes.append({"tenant_code": document_tenant_code, "tenant_name": document_tenant_name}) + if is_global: + continue if current_tenant_code: if document_tenant_code: if document_tenant_code != current_tenant_code: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户文档加入交叉评查任务: {document_id}") elif document_tenant_name != current_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户文档加入交叉评查任务: {document_id}") - elif not is_global and document_tenant_name != current_tenant_name: + elif document_tenant_name != current_tenant_name: raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"不能将其他租户文档加入交叉评查任务: {document_id}") self._assert_single_task_scope(resolved_scopes) @@ -2283,13 +2294,15 @@ class CrossReviewServiceImpl(ICrossReviewService): result.append(intValue) return result - def _to_int(self, value) -> int | None: + @staticmethod + def _to_int(value) -> int | None: """安全转 int。""" if value is None: return None return int(value) - def _parse_text_array(self, value) -> list[str]: + @staticmethod + def _parse_text_array(value) -> list[str]: """安全解析 PostgreSQL text[] 为字符串列表。""" if value is None: return [] @@ -2297,7 +2310,8 @@ class CrossReviewServiceImpl(ICrossReviewService): return [str(v) for v in value] return [str(value)] - def _parse_task_tenants(self, value) -> list[CrossReviewTaskTenantVO]: + @staticmethod + def _parse_task_tenants(value) -> list[CrossReviewTaskTenantVO]: """安全解析任务租户 JSON 聚合结果。""" if value is None: return [] @@ -2319,6 +2333,40 @@ class CrossReviewServiceImpl(ICrossReviewService): result.append(CrossReviewTaskTenantVO(tenantCode=tenant_code, tenantName=tenant_name or tenant_code)) return result + @classmethod + def _build_task_item_vo(cls, row, CanViewProgress: bool = True) -> CrossReviewTaskItemVO: + """根据进度权限组装任务列表项。""" + totalDocuments = int(row["total_documents"] or 0) + completedDocuments = int(row["completed_documents"] or 0) + progress = round((completedDocuments / totalDocuments * 100) if totalDocuments > 0 else 0, 2) + evaluationTenants = cls._parse_task_tenants(row.get("evaluation_tenants")) + rawRegions = row.get("evaluation_regions") + if rawRegions is None: + evaluationRegion: list[str] = [] + elif isinstance(rawRegions, list): + evaluationRegion = [str(r) for r in rawRegions] + else: + evaluationRegion = [str(rawRegions)] + if not evaluationRegion: + evaluationRegion = [tenant.tenantName for tenant in evaluationTenants if tenant.tenantName] + + return CrossReviewTaskItemVO( + taskId=int(row["task_id"]), + taskName=str(row["task_name"]), + taskType=str(row["task_type"]), + docTypeId=cls._to_int(row.get("doc_type_id")), + docTypeCode=row.get("doc_type_code"), + status=str(row["status"]), + progress=progress if CanViewProgress else None, + totalDocuments=totalDocuments if CanViewProgress else None, + completedDocuments=completedDocuments if CanViewProgress else None, + createdAt=row.get("create_time"), + evaluationTenants=evaluationTenants, + evaluationRegion=evaluationRegion, + currentUserRole=str(row.get("current_user_role") or "participant"), + currentUserCanConfirm=bool(row.get("current_user_can_confirm")), + ) + def _build_score_summary(self, finalScore: float, fullScore: float) -> str: if fullScore <= 0: return "0/0" diff --git a/fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py index 0c8ad15..9581ae0 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py @@ -88,6 +88,7 @@ class DocumentServiceImpl(IDocumentService): TypeId: int | None = None, TypeCode: str | None = None, GroupId: int | None = None, + EntryModuleId: int | None = None, Region: str | None = None, FileRole: str = "primary", CreatedBy: int | None = None, @@ -136,6 +137,7 @@ class DocumentServiceImpl(IDocumentService): async with GetAsyncSession() as Session: await self._ensureDocumentGroupColumn(Session) + normalizedEntryModuleId = int(EntryModuleId) if EntryModuleId is not None and int(EntryModuleId) > 0 else None if TypeId is not None and TypeCode is not None: typeResult = await Session.execute( text( @@ -182,7 +184,13 @@ class DocumentServiceImpl(IDocumentService): resolvedTypeId = int(typeRow["id"]) resolvedTypeCode = str(typeRow["code"]) - resolvedGroupId = await self._resolveDocumentGroupId(Session, resolvedTypeId, GroupId) + await self._assertDocumentTypeEntryModule(Session, resolvedTypeId, normalizedEntryModuleId) + resolvedGroupId = await self._resolveDocumentGroupId( + Session, + resolvedTypeId, + GroupId, + normalizedEntryModuleId, + ) resolvedRootGroupId = await self._resolveDocumentRootGroupId(Session, resolvedTypeId, resolvedGroupId) duplicateUpload = False previousVersionId: int | None = None @@ -236,6 +244,21 @@ class DocumentServiceImpl(IDocumentService): else: rootVersionId = document.rootVersionId + if normalizedEntryModuleId is not None: + await Session.execute( + text( + """ + UPDATE leaudit_documents + SET entry_module_id = :entry_module_id + WHERE id = :document_id + """ + ), + { + "entry_module_id": normalizedEntryModuleId, + "document_id": document.Id, + }, + ) + versionLabel = f"v{document.versionNo}" objectKey = OssPathUtils.BuildBusinessDocKey( Region=normalizedRegion, @@ -324,6 +347,7 @@ class DocumentServiceImpl(IDocumentService): typeId=resolvedTypeId, typeCode=resolvedTypeCode, groupId=resolvedGroupId, + entryModuleId=normalizedEntryModuleId, region=normalizedRegion, tenantCode=resolvedTenant.tenant_code, tenantName=resolvedTenant.tenant_name or normalizedRegion, @@ -463,6 +487,7 @@ class DocumentServiceImpl(IDocumentService): optionalSelects = [ f"{resolvedGroupIdExpr} AS group_id", + "d.entry_module_id AS entry_module_id" if "entry_module_id" in documentColumns else "NULL::bigint AS entry_module_id", "d.document_number AS document_number" if "document_number" in documentColumns else "NULL::text AS document_number", f"{persistedOrDerivedAuditStatusExpr} AS audit_status", "d.is_test_document AS is_test_document" if "is_test_document" in documentColumns else "FALSE AS is_test_document", @@ -662,6 +687,7 @@ class DocumentServiceImpl(IDocumentService): typeName=row["type_name"], groupId=int(row["group_id"]) if row["group_id"] is not None else None, groupName=row["group_name"], + entryModuleId=int(row["entry_module_id"]) if row["entry_module_id"] is not None else None, region=row["region"], tenantCode=row["tenant_code"], tenantName=row["tenant_name"], @@ -762,6 +788,26 @@ class DocumentServiceImpl(IDocumentService): scoring_proposals=scoringProposals, ) + async def IsCrossReviewDocument(self, DocumentId: int) -> bool: + """判断文档是否属于交叉评查范围。""" + async with GetAsyncSession() as Session: + row = ( + await Session.execute( + text( + """ + SELECT 1 + FROM leaudit_documents d + WHERE d.id = :document_id + AND d.deleted_at IS NULL + AND COALESCE(d.review_scope, 'standard') = 'cross_review' + LIMIT 1 + """ + ), + {"document_id": DocumentId}, + ) + ).first() + return bool(row) + async def AuditReviewPoint( self, CurrentUserId: int, @@ -2705,6 +2751,15 @@ class DocumentServiceImpl(IDocumentService): """ ) ) + await Session.execute( + text( + """ + ALTER TABLE leaudit_documents + ADD COLUMN IF NOT EXISTS entry_module_id BIGINT NULL + REFERENCES leaudit_entry_modules(id) + """ + ) + ) await Session.execute( text( """ @@ -2717,23 +2772,71 @@ class DocumentServiceImpl(IDocumentService): await Session.execute( text("CREATE INDEX IF NOT EXISTS idx_leaudit_documents_group_id ON leaudit_documents(group_id)") ) + await Session.execute( + text("CREATE INDEX IF NOT EXISTS idx_leaudit_documents_entry_module_id ON leaudit_documents(entry_module_id)") + ) await Session.execute( text("CREATE INDEX IF NOT EXISTS idx_leaudit_documents_tenant_code ON leaudit_documents(tenant_code)") ) - async def _resolveDocumentGroupId(self, Session, TypeId: int, GroupId: int | None) -> int | None: - """校验上传时选择的二级分组是否属于当前文档类型。""" - if GroupId is None: - return None + async def _assertDocumentTypeEntryModule( + self, + Session, + TypeId: int, + EntryModuleId: int | None, + ) -> None: + if EntryModuleId is None: + return row = ( await Session.execute( text( """ - SELECT id, document_type_id, name - FROM leaudit_evaluation_point_groups - WHERE id = :group_id + SELECT id, name, entry_module_id + FROM leaudit_document_types + WHERE id = :type_id AND deleted_at IS NULL - AND COALESCE(pid, 0) <> 0 + LIMIT 1 + """ + ), + {"type_id": TypeId}, + ) + ).mappings().first() + if not row: + raise LeauditException(StatusCodeEnum.HTTP_404_NOT_FOUND, "文档类型不存在或已停用") + if int(row.get("entry_module_id") or 0) != EntryModuleId: + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + f"文档类型「{row['name']}」不属于当前入口模块,无法上传", + ) + + async def _resolveDocumentGroupId( + self, + Session, + TypeId: int, + GroupId: int | None, + EntryModuleId: int | None = None, + ) -> int | None: + """校验上传时选择的二级分组是否属于当前文档类型。""" + if GroupId is None: + return await self._resolveUniqueDocumentGroupId(Session, TypeId, EntryModuleId) + row = ( + await Session.execute( + text( + """ + SELECT + child.id, + child.document_type_id, + child.name, + COALESCE(child.entry_module_id, parent.entry_module_id, dt.entry_module_id) AS entry_module_id + FROM leaudit_evaluation_point_groups child + LEFT JOIN leaudit_evaluation_point_groups parent + ON parent.id = child.pid + LEFT JOIN leaudit_document_types dt + ON dt.id = child.document_type_id + WHERE child.id = :group_id + AND child.deleted_at IS NULL + AND COALESCE(child.pid, 0) <> 0 + AND child.is_enabled = true LIMIT 1 """ ), @@ -2748,8 +2851,63 @@ class DocumentServiceImpl(IDocumentService): TypeId, GroupId, row["document_type_id"], row["name"], ) raise LeauditException(StatusCodeEnum.HTTP_400_BAD_REQUEST, f"当前子类型「{row['name']}」(id={GroupId}) 属于文档类型 {row['document_type_id']},与所选文档类型 {TypeId} 不匹配,无法上传") + if EntryModuleId is not None and int(row.get("entry_module_id") or 0) != EntryModuleId: + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + f"当前子类型「{row['name']}」不属于当前入口模块,无法上传", + ) return int(row["id"]) + async def _resolveUniqueDocumentGroupId( + self, + Session, + TypeId: int, + EntryModuleId: int | None = None, + ) -> int | None: + params: dict[str, int] = {"type_id": TypeId} + entry_module_filter = "" + if EntryModuleId is not None: + entry_module_filter = """ + AND COALESCE(child.entry_module_id, parent.entry_module_id, dt.entry_module_id) = :entry_module_id + """ + params["entry_module_id"] = int(EntryModuleId) + rows = ( + await Session.execute( + text( + f""" + SELECT + child.id, + child.name, + COALESCE(child.entry_module_id, parent.entry_module_id, dt.entry_module_id) AS entry_module_id + FROM leaudit_evaluation_point_groups child + LEFT JOIN leaudit_evaluation_point_groups parent + ON parent.id = child.pid + LEFT JOIN leaudit_document_types dt + ON dt.id = child.document_type_id + WHERE child.document_type_id = :type_id + AND child.deleted_at IS NULL + AND COALESCE(child.pid, 0) <> 0 + AND child.is_enabled = true + {entry_module_filter} + ORDER BY COALESCE(child.sort_order, 0) ASC, child.id ASC + LIMIT 2 + """ + ), + params, + ) + ).mappings().all() + if len(rows) == 1: + return int(rows[0]["id"]) + if len(rows) > 1: + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + "当前文档类型存在多个子类型,请选择具体子类型后再上传", + ) + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + "当前文档类型未配置可用子类型,请先在评查点分组管理中配置二级分组", + ) + async def _resolveDocumentRootGroupId(self, Session, TypeId: int, GroupId: int | None) -> int | None: """解析上传命中的一级分组,用于跨二级类型做版本归档。""" if GroupId is not None: @@ -2942,6 +3100,7 @@ class DocumentServiceImpl(IDocumentService): optionalSelects = [ f"{resolvedGroupIdExpr} AS group_id", + "d.entry_module_id AS entry_module_id" if "entry_module_id" in DocumentColumns else "NULL::bigint AS entry_module_id", "d.document_number AS document_number" if "document_number" in DocumentColumns else "NULL::text AS document_number", "d.remark AS remark" if "remark" in DocumentColumns else "NULL::text AS remark", "d.is_test_document AS is_test_document" if "is_test_document" in DocumentColumns else "FALSE AS is_test_document", @@ -3149,6 +3308,7 @@ class DocumentServiceImpl(IDocumentService): typeName=detailRow["type_name"], groupId=int(detailRow["group_id"]) if detailRow["group_id"] is not None else None, groupName=detailRow["group_name"], + entryModuleId=int(detailRow["entry_module_id"]) if detailRow["entry_module_id"] is not None else None, region=str(detailRow["region"] or ""), tenantCode=detailRow["tenant_code"], tenantName=detailRow["tenant_name"], @@ -3562,6 +3722,9 @@ class DocumentServiceImpl(IDocumentService): pageCount = int(metricRow["page_count"]) if metricRow and metricRow["page_count"] is not None else 0 ocrResultPayload = await self._buildReviewOcrPayload(Session, Detail.documentId, RunRow, pageCount) + pageQualityResults = [] + if Detail.pageQualityRunId is not None: + pageQualityResults = await self._loadPageQualityIssueResults(Session, int(Detail.pageQualityRunId)) return { "id": Detail.documentId, @@ -3593,8 +3756,66 @@ class DocumentServiceImpl(IDocumentService): "page_count": pageCount, "ocrResult": ocrResultPayload, "attachments": [item.model_dump() for item in Detail.attachments], + **self._buildReviewPageQualityPayload(Detail, pageQualityResults), } + @staticmethod + def _buildReviewPageQualityPayload( + Detail: DocumentDetailVO, + PageQualityResults: list[dict[str, Any]] | None = None, + ) -> dict[str, Any]: + """构建评查详情页需要的图片质量摘要字段。""" + page_quality_summary = Detail.pageQualitySummary.model_dump() if Detail.pageQualitySummary else None + status_order = {"reject": 0, "review": 1} + page_quality_results = sorted( + PageQualityResults or [], + key=lambda item: ( + status_order.get(str(item.get("qualityStatus") or ""), 9), + int(item.get("pageNum") or 0), + ), + ) + return { + "pageQualityRunId": Detail.pageQualityRunId, + "pageQualityRunStatus": Detail.pageQualityRunStatus, + "pageQualitySummaryStatus": Detail.pageQualitySummaryStatus, + "pageQualityIssueCount": Detail.pageQualityIssueCount, + "pageQualityWarningText": Detail.pageQualityWarningText, + "pageQualitySummary": page_quality_summary, + "pageQualityResults": page_quality_results, + } + + async def _loadPageQualityIssueResults(self, Session, RunId: int) -> list[dict[str, Any]]: + """加载页级图片质量问题明细。""" + if not await self._tableExists(Session, "leaudit_page_quality_results"): + return [] + rows = ( + await Session.execute( + text( + """ + SELECT page_num, quality_status, quality_score, reason_text + FROM leaudit_page_quality_results + WHERE run_id = :run_id + AND quality_status IN ('review', 'reject') + ORDER BY + CASE quality_status WHEN 'reject' THEN 0 WHEN 'review' THEN 1 ELSE 9 END, + page_num ASC, + id ASC + """ + ), + {"run_id": RunId}, + ) + ).mappings().all() + return [ + { + "pageNum": int(row["page_num"]), + "qualityStatus": str(row["quality_status"] or "review"), + "qualityScore": float(row["quality_score"]) if row["quality_score"] is not None else None, + "reasonText": str(row["reason_text"] or "") or None, + } + for row in rows + if row["page_num"] is not None + ] + async def _buildReviewOcrPayload( self, Session, diff --git a/fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py index ea926f9..56cefb8 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/entryModuleAdminServiceImpl.py @@ -21,6 +21,7 @@ from fastapi_modules.fastapi_leaudit.domian.Dto.entryModuleDto import ( EntryModuleUpdateDTO, ) from fastapi_modules.fastapi_leaudit.domian.vo.entryModuleAdminVo import ( + EntryModuleBusinessScopeVO, EntryModuleImageUploadVO, EntryModuleListVO, EntryModuleTenantVO, @@ -31,6 +32,31 @@ from fastapi_modules.fastapi_leaudit.services.impl.ossServiceImpl import OssServ from fastapi_modules.fastapi_leaudit.services.impl.tenantResolver import TenantResolution, TenantResolver +_ALLOWED_MENU_PROFILES = {"document_review", "contract", "govdoc", "cross_checking", "custom"} +_ALLOWED_FEATURES = { + "home", + "documents", + "upload", + "rules", + "rule_groups", + "contract_template_search", + "contract_template_list", + "govdoc_audits", + "govdoc_upload", + "cross_checking", + "cross_checking_upload", + "cross_checking_list", + "usage_stats", +} +_DEFAULT_FEATURES_BY_PROFILE = { + "document_review": ["home", "documents", "upload", "rules", "rule_groups"], + "contract": ["home", "documents", "upload", "rules", "contract_template_search", "contract_template_list"], + "govdoc": ["home", "govdoc_audits", "govdoc_upload", "rule_groups"], + "cross_checking": ["cross_checking", "cross_checking_upload", "cross_checking_list"], + "custom": ["home", "documents"], +} + + class EntryModuleAdminServiceImpl(IEntryModuleAdminService): """入口模块管理服务实现。""" @@ -39,6 +65,7 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): self.TenantResolver = TenantResolver() self._tenant_table_exists_cache: bool | None = None self._entry_module_tenant_table_exists_cache: bool | None = None + self._entry_module_menu_columns_exist_cache: bool | None = None async def ListModules( self, @@ -128,6 +155,8 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): if has_tenant_mapping_table else "'[]'::jsonb AS tenants" ) + menu_select_sql = await self._entry_module_menu_select_sql() + business_scope_select_sql = self._entry_module_business_scope_select_sql() async with GetAsyncSession() as session: total = int( @@ -154,6 +183,8 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): em.is_enabled, em.created_at, em.updated_at, + {menu_select_sql}, + {business_scope_select_sql}, {tenant_select_sql} FROM leaudit_entry_modules em WHERE {where_clause} @@ -182,29 +213,37 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): ) self._ensureTenantAssignments(normalized_tenants) legacy_areas_json = self._legacyAreasJson(normalized_tenants) + menu_profile = self._normalizeMenuProfile(Body.menu_profile) + features = self._normalizeFeatures(Body.features, menu_profile) + has_menu_columns = await self._entry_module_menu_columns_exist() async with GetAsyncSession() as session: try: + menu_insert_columns = ", menu_profile, features" if has_menu_columns else "" + menu_insert_values = ", :menu_profile, CAST(:features AS jsonb)" if has_menu_columns else "" + params = { + "name": Body.name.strip(), + "description": (Body.description or "").strip() or None, + "route_path": route_path, + "icon_path": None, + "areas": legacy_areas_json, + "sort_order": await self._nextSortOrder(session), + "menu_profile": menu_profile, + "features": json.dumps(features, ensure_ascii=False), + } row = ( await session.execute( text( - """ + f""" INSERT INTO leaudit_entry_modules ( - name, description, path, icon_path, areas, sort_order, is_enabled, created_at, updated_at, deleted_at + name, description, path, icon_path, areas, sort_order, is_enabled, created_at, updated_at, deleted_at{menu_insert_columns} ) VALUES ( - :name, :description, :route_path, :icon_path, CAST(:areas AS jsonb), :sort_order, TRUE, NOW(), NOW(), NULL + :name, :description, :route_path, :icon_path, CAST(:areas AS jsonb), :sort_order, TRUE, NOW(), NOW(), NULL{menu_insert_values} ) RETURNING id """ ), - { - "name": Body.name.strip(), - "description": (Body.description or "").strip() or None, - "route_path": route_path, - "icon_path": None, - "areas": legacy_areas_json, - "sort_order": await self._nextSortOrder(session), - }, + params, ) ).mappings().one() module_id = int(row["id"]) @@ -226,12 +265,30 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): else: normalized_tenants = await self._extractTenantsFromRow(current) self._ensureTenantAssignments(normalized_tenants) + current_menu_profile = self._safeMenuProfile(current.get("menu_profile")) + menu_profile = self._normalizeMenuProfile(Body.menu_profile) if Body.menu_profile is not None else current_menu_profile + features = ( + self._normalizeFeatures(Body.features, menu_profile) + if Body.features is not None + else self._parseFeatures(current.get("features"), menu_profile) + ) + has_menu_columns = await self._entry_module_menu_columns_exist() async with GetAsyncSession() as session: + menu_update_sql = ", menu_profile = :menu_profile, features = CAST(:features AS jsonb)" if has_menu_columns else "" + params = { + "module_id": ModuleId, + "name": Body.name.strip() if Body.name is not None else current["name"], + "description": Body.description.strip() if Body.description is not None else current.get("description"), + "route_path": incoming_route_path.strip() if incoming_route_path is not None else current.get("path"), + "areas": self._legacyAreasJson(normalized_tenants), + "menu_profile": menu_profile, + "features": json.dumps(features, ensure_ascii=False), + } row = ( await session.execute( text( - """ + f""" UPDATE leaudit_entry_modules SET name = :name, @@ -239,18 +296,13 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): path = :route_path, areas = CAST(:areas AS jsonb), updated_at = NOW() + {menu_update_sql} WHERE id = :module_id AND deleted_at IS NULL RETURNING id """ ), - { - "module_id": ModuleId, - "name": Body.name.strip() if Body.name is not None else current["name"], - "description": Body.description.strip() if Body.description is not None else current.get("description"), - "route_path": incoming_route_path.strip() if incoming_route_path is not None else current.get("path"), - "areas": self._legacyAreasJson(normalized_tenants), - }, + params, ) ).mappings().first() if not row: @@ -341,6 +393,8 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): if has_tenant_mapping_table else "'[]'::jsonb AS tenants" ) + menu_select_sql = await self._entry_module_menu_select_sql() + business_scope_select_sql = self._entry_module_business_scope_select_sql() async with GetAsyncSession() as session: row = ( await session.execute( @@ -357,6 +411,8 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): em.is_enabled, em.created_at, em.updated_at, + {menu_select_sql}, + {business_scope_select_sql}, {tenant_select_sql} FROM leaudit_entry_modules em WHERE em.id = :module_id @@ -386,9 +442,12 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): description=Row.get("description"), path=Row.get("icon_path"), route_path=Row.get("path"), + menu_profile=self._safeMenuProfile(Row.get("menu_profile")), + features=self._parseFeatures(Row.get("features"), Row.get("menu_profile")), sort_order=int(Row.get("sort_order") or 0), is_enabled=bool(Row.get("is_enabled", True)), tenants=tenants, + business_scope=self._parseBusinessScope(Row.get("business_scope")), created_at=self._toIso(Row.get("created_at")), updated_at=self._toIso(Row.get("updated_at")), ) @@ -568,6 +627,102 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): self._entry_module_tenant_table_exists_cache = exists return exists + async def _entry_module_menu_columns_exist(self) -> bool: + if self._entry_module_menu_columns_exist_cache is not None: + return self._entry_module_menu_columns_exist_cache + async with GetAsyncSession() as session: + count = int( + ( + await session.execute( + text( + """ + SELECT COUNT(*) + FROM information_schema.columns + WHERE table_schema = current_schema() + AND table_name = 'leaudit_entry_modules' + AND column_name IN ('menu_profile', 'features') + """ + ) + ) + ).scalar_one() + ) + self._entry_module_menu_columns_exist_cache = count == 2 + return self._entry_module_menu_columns_exist_cache + + async def _entry_module_menu_select_sql(self) -> str: + if await self._entry_module_menu_columns_exist(): + return "em.menu_profile, em.features" + return "'document_review'::varchar AS menu_profile, '[]'::jsonb AS features" + + def _entry_module_business_scope_select_sql(self) -> str: + return """ + COALESCE( + ( + SELECT jsonb_build_object( + 'category_count', COUNT(DISTINCT dt.id), + 'business_type_count', GREATEST( + COUNT(DISTINCT child_by_type.id), + COALESCE( + ( + SELECT COUNT(DISTINCT child_by_entry.id) + FROM leaudit_evaluation_point_groups root_by_entry + JOIN leaudit_evaluation_point_groups child_by_entry + ON child_by_entry.pid = root_by_entry.id + AND child_by_entry.deleted_at IS NULL + WHERE root_by_entry.entry_module_id = em.id + AND root_by_entry.pid = 0 + AND root_by_entry.deleted_at IS NULL + ), + 0 + ) + ), + 'categories', COALESCE( + ( + SELECT jsonb_agg(category_name ORDER BY category_name) + FROM ( + SELECT DISTINCT dt2.name AS category_name + FROM leaudit_document_types dt2 + WHERE dt2.entry_module_id = em.id + AND dt2.deleted_at IS NULL + AND dt2.is_enabled = TRUE + ) category_rows + ), + '[]'::jsonb + ) + ) + FROM leaudit_document_types dt + LEFT JOIN leaudit_evaluation_point_groups root + ON root.document_type_id = dt.id + AND root.pid = 0 + AND root.deleted_at IS NULL + LEFT JOIN leaudit_evaluation_point_groups child_by_type + ON child_by_type.pid = root.id + AND child_by_type.deleted_at IS NULL + WHERE dt.entry_module_id = em.id + AND dt.deleted_at IS NULL + AND dt.is_enabled = TRUE + ), + jsonb_build_object('category_count', 0, 'business_type_count', 0, 'categories', '[]'::jsonb) + ) AS business_scope + """ + + def _parseBusinessScope(self, RawValue: object) -> EntryModuleBusinessScopeVO: + if isinstance(RawValue, str): + try: + RawValue = json.loads(RawValue) + except json.JSONDecodeError: + RawValue = {} + if not isinstance(RawValue, dict): + RawValue = {} + + categories_raw = RawValue.get("categories") or [] + categories = [str(item).strip() for item in categories_raw if str(item or "").strip()] if isinstance(categories_raw, list) else [] + return EntryModuleBusinessScopeVO( + category_count=int(RawValue.get("category_count") or len(categories)), + business_type_count=int(RawValue.get("business_type_count") or 0), + categories=categories, + ) + async def _resolveLegacyTenantValue(self, *, RawValue: str, Source: str) -> TenantResolution: resolution = await self.TenantResolver.Resolve( RawValue=RawValue, @@ -705,6 +860,65 @@ class EntryModuleAdminServiceImpl(IEntryModuleAdminService): "入口模块至少需要配置一个适用租户", ) + @staticmethod + def _normalizeMenuProfile(MenuProfile: str | None) -> str: + value = str(MenuProfile or "document_review").strip() or "document_review" + if value not in _ALLOWED_MENU_PROFILES: + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + f"不支持的菜单模板: {value}", + ) + return value + + @staticmethod + def _safeMenuProfile(MenuProfile: str | None) -> str: + value = str(MenuProfile or "document_review").strip() or "document_review" + return value if value in _ALLOWED_MENU_PROFILES else "document_review" + + @staticmethod + def _normalizeFeatures(Features: list[str] | None, MenuProfile: str) -> list[str]: + raw_features = Features if Features else _DEFAULT_FEATURES_BY_PROFILE.get(MenuProfile, _DEFAULT_FEATURES_BY_PROFILE["document_review"]) + normalized: list[str] = [] + invalid: list[str] = [] + for item in raw_features: + feature = str(item or "").strip() + if not feature: + continue + if feature not in _ALLOWED_FEATURES: + invalid.append(feature) + continue + if feature not in normalized: + normalized.append(feature) + if invalid: + raise LeauditException( + StatusCodeEnum.HTTP_400_BAD_REQUEST, + f"不支持的功能编码: {', '.join(invalid)}", + ) + return normalized or list(_DEFAULT_FEATURES_BY_PROFILE.get(MenuProfile, _DEFAULT_FEATURES_BY_PROFILE["document_review"])) + + @classmethod + def _parseFeatures(cls, RawFeatures: Any, MenuProfile: str | None) -> list[str]: + menu_profile = cls._safeMenuProfile(MenuProfile) + if isinstance(RawFeatures, list): + return cls._filterFeatures([str(item) for item in RawFeatures], menu_profile) + if isinstance(RawFeatures, str) and RawFeatures.strip(): + try: + parsed = json.loads(RawFeatures) + except json.JSONDecodeError: + parsed = [] + if isinstance(parsed, list): + return cls._filterFeatures([str(item) for item in parsed], menu_profile) + return list(_DEFAULT_FEATURES_BY_PROFILE.get(menu_profile, _DEFAULT_FEATURES_BY_PROFILE["document_review"])) + + @staticmethod + def _filterFeatures(Features: list[str], MenuProfile: str) -> list[str]: + normalized: list[str] = [] + for item in Features: + feature = str(item or "").strip() + if feature in _ALLOWED_FEATURES and feature not in normalized: + normalized.append(feature) + return normalized or list(_DEFAULT_FEATURES_BY_PROFILE.get(MenuProfile, _DEFAULT_FEATURES_BY_PROFILE["document_review"])) + @staticmethod def _toIso(Value) -> str | None: """时间转 ISO 字符串。""" diff --git a/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py index b896bfe..6a33d87 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py @@ -62,6 +62,7 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): Page: int, PageSize: int, CurrentUserId: int, + EntryModuleId: int | None = None, ) -> EvaluationPointGroupListVO: async with GetAsyncSession() as session: await self._ensure_ready(session) @@ -97,6 +98,10 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): if Pid is not None: filters.append("COALESCE(g.pid, 0) = :pid") params["pid"] = self._normalize_pid(Pid) + if EntryModuleId is not None: + await self._assert_entry_module_access(session, EntryModuleId, current_user) + filters.append("COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) = :entry_module_id") + params["entry_module_id"] = int(EntryModuleId) where_clause = " AND ".join(filters) total = int( @@ -149,7 +154,13 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): page_size=PageSize, ) - async def ListAllGroups(self, IncludeDisabled: bool, WithRuleCount: bool, CurrentUserId: int) -> list[EvaluationPointGroupVO]: + async def ListAllGroups( + self, + IncludeDisabled: bool, + WithRuleCount: bool, + CurrentUserId: int, + EntryModuleId: int | None = None, + ) -> list[EvaluationPointGroupVO]: async with GetAsyncSession() as session: await self._ensure_ready(session) current_user = await self._get_current_user_context(session, CurrentUserId) @@ -166,6 +177,10 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): ) if not IncludeDisabled: filters.append("g.is_enabled = TRUE") + if EntryModuleId is not None: + await self._assert_entry_module_access(session, EntryModuleId, current_user) + filters.append("COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) = :entry_module_id") + params["entry_module_id"] = int(EntryModuleId) rows = ( await session.execute( text( @@ -233,6 +248,7 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): IncludeDisabled=IncludeDisabled, WithRuleCount=WithRuleCount, CurrentUserId=CurrentUserId, + EntryModuleId=None, ) result: list[EvaluationPointGroupVO] = [] for root in roots: @@ -262,6 +278,7 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): Page=Page, PageSize=PageSize, CurrentUserId=CurrentUserId, + EntryModuleId=None, ) async def CreateGroup(self, Body: EvaluationPointGroupCreateDTO, CurrentUserId: int) -> EvaluationPointGroupVO: @@ -760,7 +777,7 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): row = ( await session.execute( text( - """ + f""" SELECT rgb.id, rgb.group_id, @@ -798,30 +815,43 @@ class EvaluationPointGroupServiceImpl(IEvaluationPointGroupService): group_ids = [int(item) for item in group_ids if item] if not group_ids: return {} + params: dict[str, Any] = {"group_ids": group_ids} + tenant_filter = "" + if current_user is not None and not current_user.get("is_global"): + visible_tenant_codes = ["PUBLIC", "PROVINCIAL"] + tenant_code = normalize_scoped_tenant_code(str(current_user.get("tenant_code") or ""), default="") + if tenant_code: + visible_tenant_codes.append(tenant_code) + tenant_filter = """ + AND COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL') IN :visible_tenant_codes + """ + params["visible_tenant_codes"] = sorted(set(visible_tenant_codes)) + query = text( + f""" + SELECT + id, + group_id, + rule_set_id, + rule_type_binding_id, + COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL') AS tenant_code, + COALESCE(NULLIF(BTRIM(scope_type), ''), 'PROVINCIAL') AS scope_type, + tenant_name_snapshot, + priority, + is_active, + note, + created_at, + updated_at + FROM leaudit_rule_group_bindings + WHERE group_id IN :group_ids + AND deleted_at IS NULL + {tenant_filter} + ORDER BY priority DESC, id ASC + """ + ).bindparams(bindparam("group_ids", expanding=True)) + if "visible_tenant_codes" in params: + query = query.bindparams(bindparam("visible_tenant_codes", expanding=True)) rows = ( - await session.execute( - text( - """ - SELECT - id, - group_id, - rule_set_id, - rule_type_binding_id, - COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL') AS tenant_code, - COALESCE(NULLIF(BTRIM(scope_type), ''), 'PROVINCIAL') AS scope_type, - tenant_name_snapshot, - priority, - is_active, - note, - created_at, - updated_at - FROM leaudit_rule_group_bindings - WHERE group_id IN :group_ids AND deleted_at IS NULL - ORDER BY priority DESC, id ASC - """ - ).bindparams(bindparam("group_ids", expanding=True)), - {"group_ids": group_ids}, - ) + await session.execute(query, params) ).mappings().all() result: dict[int, list[RuleGroupBindingVO]] = {} for row in rows: diff --git a/fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py index 069dde4..10b18f8 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py @@ -101,6 +101,7 @@ class GovdocServiceImpl(IGovdocService): self, file: UploadFile, typeId: int | None = None, + entryModuleId: int | None = None, region: str | None = None, tenantCode: str | None = None, autoRun: bool = True, @@ -229,11 +230,15 @@ class GovdocServiceImpl(IGovdocService): text( """ UPDATE leaudit_documents - SET engine_type = 'govdoc' + SET engine_type = 'govdoc', + entry_module_id = COALESCE(:entry_module_id, entry_module_id) WHERE id = :document_id """ ), - {"document_id": document.Id}, + { + "document_id": document.Id, + "entry_module_id": int(entryModuleId) if entryModuleId is not None and int(entryModuleId) > 0 else None, + }, ) await session.commit() @@ -273,6 +278,8 @@ class GovdocServiceImpl(IGovdocService): fileExt: str | None = None, region: str | None = None, tenantCode: str | None = None, + entryModuleId: int | None = None, + typeIds: list[int] | None = None, status: str | None = None, resultStatus: str | None = None, createdBy: int | None = None, @@ -327,6 +334,13 @@ class GovdocServiceImpl(IGovdocService): if normalizedExt: filters.append("LOWER(COALESCE(f.file_ext, '')) = :file_ext") params["file_ext"] = normalizedExt + normalizedTypeIds = [int(typeId) for typeId in (typeIds or []) if int(typeId) > 0] + if normalizedTypeIds: + filters.append("d.type_id = ANY(:type_ids)") + params["type_ids"] = normalizedTypeIds + if entryModuleId is not None and int(entryModuleId) > 0: + filters.append("COALESCE(d.entry_module_id, dt.entry_module_id) = :entry_module_id") + params["entry_module_id"] = int(entryModuleId) if status: filters.append("COALESCE(d.processing_status, '') = :status") params["status"] = status.strip() @@ -420,6 +434,8 @@ class GovdocServiceImpl(IGovdocService): AND f.deleted_at IS NULL LEFT JOIN govdoc_runs gr ON gr.id = d.current_run_id + LEFT JOIN leaudit_document_types dt + ON dt.id = d.type_id LEFT JOIN ( SELECT run_id, @@ -1236,6 +1252,10 @@ class GovdocServiceImpl(IGovdocService): """, """ ALTER TABLE leaudit_documents + ADD COLUMN IF NOT EXISTS entry_module_id BIGINT + """, + """ + ALTER TABLE leaudit_documents ADD COLUMN IF NOT EXISTS engine_type VARCHAR(32) NOT NULL DEFAULT 'leaudit' """, """ diff --git a/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py index 89d9f01..9e79fa5 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py @@ -2,6 +2,10 @@ from __future__ import annotations +from datetime import date, datetime +import json +from typing import Any + from sqlalchemy import text from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession @@ -9,12 +13,16 @@ from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException from fastapi_modules.fastapi_leaudit.domian.vo.homeVo import ( + HomeDashboardGrowthVO, + HomeDashboardStatisticsVO, HomeEntryAreaVO, HomeEntryDocumentTypeVO, HomeEntryModuleVO, HomeEntryTenantVO, ) +from fastapi_modules.fastapi_leaudit.services import IDocumentService from fastapi_modules.fastapi_leaudit.services.homeService import IHomeService +from fastapi_modules.fastapi_leaudit.services.impl.documentServiceImpl import DocumentServiceImpl from fastapi_modules.fastapi_leaudit.services.impl.rbacServiceImpl import RbacServiceImpl from fastapi_modules.fastapi_leaudit.services.impl.ssoUserCompat import SsoUserCompat from fastapi_modules.fastapi_leaudit.services.impl.tenantResolver import TenantResolution, TenantResolver @@ -29,17 +37,34 @@ class HomeServiceImpl(IHomeService): "/documents", "/chat-with-llm/chat", "/cross-checking", + "/govdoc", + "/govdoc/home", + "/govdoc/audits", + "/govdoc/upload", + "/govdoc-audit", + "/govdoc-audit/home", + "/govdoc-audit/audits", + "/govdoc-audit/upload", ) _DOCUMENT_ENTRY_TARGETS: tuple[str, ...] = ( "/files/upload", "/documents", "/documents/list", ) + _DEFAULT_FEATURES_BY_PROFILE: dict[str, list[str]] = { + "document_review": ["home", "documents", "upload", "rules", "rule_groups"], + "contract": ["home", "documents", "upload", "rules", "contract_template_search", "contract_template_list"], + "govdoc": ["home", "govdoc_audits", "govdoc_upload", "rule_groups"], + "cross_checking": ["cross_checking", "cross_checking_upload", "cross_checking_list"], + "custom": ["home", "documents"], + } - def __init__(self) -> None: + def __init__(self, DocumentService: IDocumentService | None = None) -> None: self.RbacService = RbacServiceImpl() self.TenantResolver = TenantResolver() + self.DocumentService = DocumentService or DocumentServiceImpl() self._entry_module_tenant_table_exists_cache: bool | None = None + self._entry_module_menu_columns_exist_cache: bool | None = None async def GetEntryModules(self, UserId: int) -> list[HomeEntryModuleVO]: """获取当前用户可见的首页入口模块。""" @@ -125,6 +150,9 @@ class HomeServiceImpl(IHomeService): if has_tenant_mapping_table else "'[]'::jsonb AS tenants" ) + has_menu_columns = await self._entry_module_menu_columns_exist() + menu_select_sql = self._entry_module_menu_select_sql(has_menu_columns) + menu_group_by_sql = ",\n em.menu_profile,\n em.features" if has_menu_columns else "" tenant_scope_filter_sql = ( """ ( @@ -195,6 +223,7 @@ class HomeServiceImpl(IHomeService): em.icon_path, em.areas, em.sort_order, + {menu_select_sql}, {tenant_select_sql}, COALESCE( json_agg( @@ -225,6 +254,7 @@ class HomeServiceImpl(IHomeService): em.icon_path, em.areas, em.sort_order + {menu_group_by_sql} ORDER BY em.sort_order ASC, em.id ASC """ ), @@ -311,6 +341,9 @@ class HomeServiceImpl(IHomeService): description=row["description"], targetPath=target_path, routePath=target_path, + menuProfile=self._normalizeMenuProfile(row.get("menu_profile")), + features=self._parseFeatures(row.get("features"), row.get("menu_profile")), + tenantCode=effective_tenant_code or None, iconPath=row["icon_path"], sortOrder=int(row["sort_order"] or 0), requiresDocumentTypes=requires_document_types, @@ -322,6 +355,95 @@ class HomeServiceImpl(IHomeService): return modules + async def GetDashboardStatistics( + self, + UserId: int, + Today: str | None = None, + TypeIds: list[int] | None = None, + EntryModuleId: int | None = None, + ) -> HomeDashboardStatisticsVO: + """获取当前业务入口的首页统计卡片数据。""" + today = date.fromisoformat(Today) if Today else date.today() + current_month_start = today.replace(day=1) + previous_month_end = current_month_start.fromordinal(current_month_start.toordinal() - 1) + previous_month_start = previous_month_end.replace(day=1) + normalized_type_ids = [int(typeId) for typeId in (TypeIds or []) if int(typeId) > 0] + normalized_entry_module_id = int(EntryModuleId) if EntryModuleId and int(EntryModuleId) > 0 else None + + async def load_documents() -> list[Any]: + page = 1 + documents: list[Any] = [] + while True: + result = await self.DocumentService.ListDocuments( + CurrentUserId=UserId, + Page=page, + PageSize=100, + TypeIds=normalized_type_ids or None, + EntryModuleId=normalized_entry_module_id, + ) + documents.extend(result.documents) + total_pages = max(1, int(result.totalPages or 1)) + if page >= total_pages: + return documents + page += 1 + + def issue_count(Documents: list[Any]) -> int: + return sum(max(0, int(document.failedCount or 0)) for document in Documents) + + def pass_rate(Documents: list[Any]) -> int: + if not Documents: + return 0 + passed_count = len([document for document in Documents if int(document.failedCount or 0) == 0]) + return round((passed_count / len(Documents)) * 100) + + def growth(Current: int, Previous: int) -> HomeDashboardGrowthVO: + if Previous <= 0: + return HomeDashboardGrowthVO(value=100 if Current > 0 else 0, isUp=Current >= Previous) + return HomeDashboardGrowthVO( + value=round(abs(((Current - Previous) / Previous) * 100)), + isUp=Current >= Previous, + ) + + def document_date(Document: Any) -> date | None: + raw_value = str(getattr(Document, "updatedAt", "") or "").strip() + if not raw_value: + return None + normalized = raw_value.replace("Z", "+00:00") + try: + return datetime.fromisoformat(normalized).date() + except ValueError: + try: + return datetime.strptime(raw_value, "%Y-%m-%d %H:%M:%S").date() + except ValueError: + return None + + def in_range(Document: Any, DateFrom: date, DateTo: date) -> bool: + current_date = document_date(Document) + return current_date is not None and DateFrom <= current_date <= DateTo + + documents = await load_documents() + today_documents = [document for document in documents if in_range(document, today, today)] + current_month_documents = [document for document in documents if in_range(document, current_month_start, today)] + previous_month_documents = [ + document for document in documents if in_range(document, previous_month_start, previous_month_end) + ] + current_reviewed_documents = [document for document in current_month_documents if int(document.auditStatus or 0) == 1] + previous_reviewed_documents = [document for document in previous_month_documents if int(document.auditStatus or 0) == 1] + current_pass_rate = pass_rate(current_reviewed_documents) + previous_pass_rate = pass_rate(previous_reviewed_documents) + current_issue_count = issue_count(current_reviewed_documents) + previous_issue_count = issue_count(previous_reviewed_documents) + + return HomeDashboardStatisticsVO( + todayPendingFiles=len([document for document in today_documents if int(document.auditStatus or 0) != 1]), + monthlyReviewedFiles=len(current_reviewed_documents), + monthlyReviewGrowth=growth(len(current_reviewed_documents), len(previous_reviewed_documents)), + monthlyPassRate=current_pass_rate, + passRateGrowth=growth(current_pass_rate, previous_pass_rate), + issuesDetected=current_issue_count, + issuesGrowth=growth(current_issue_count, previous_issue_count), + ) + async def _entry_module_tenant_table_exists(self) -> bool: if self._entry_module_tenant_table_exists_cache is not None: return self._entry_module_tenant_table_exists_cache @@ -345,6 +467,75 @@ class HomeServiceImpl(IHomeService): self._entry_module_tenant_table_exists_cache = exists return exists + async def _entry_module_menu_columns_exist(self) -> bool: + if self._entry_module_menu_columns_exist_cache is not None: + return self._entry_module_menu_columns_exist_cache + async with GetAsyncSession() as session: + count = int( + ( + await session.execute( + text( + """ + SELECT COUNT(*) + FROM information_schema.columns + WHERE table_schema = current_schema() + AND table_name = 'leaudit_entry_modules' + AND column_name IN ('menu_profile', 'features') + """ + ) + ) + ).scalar_one() + ) + self._entry_module_menu_columns_exist_cache = count == 2 + return self._entry_module_menu_columns_exist_cache + + @staticmethod + def _entry_module_menu_select_sql(HasMenuColumns: bool) -> str: + if HasMenuColumns: + return "em.menu_profile, em.features" + return "'document_review'::varchar AS menu_profile, '[]'::jsonb AS features" + + @classmethod + def _normalizeMenuProfile(cls, MenuProfile: str | None) -> str: + value = str(MenuProfile or "document_review").strip() or "document_review" + if value not in cls._DEFAULT_FEATURES_BY_PROFILE: + return "document_review" + return value + + @classmethod + def _parseFeatures(cls, RawFeatures: Any, MenuProfile: str | None) -> list[str]: + menu_profile = cls._normalizeMenuProfile(MenuProfile) + allowed_features = { + "home", + "documents", + "upload", + "rules", + "rule_groups", + "contract_template_search", + "contract_template_list", + "govdoc_audits", + "govdoc_upload", + "cross_checking", + "cross_checking_upload", + "cross_checking_list", + "usage_stats", + } + if isinstance(RawFeatures, list): + parsed = RawFeatures + elif isinstance(RawFeatures, str) and RawFeatures.strip(): + try: + parsed = json.loads(RawFeatures) + except json.JSONDecodeError: + parsed = [] + else: + parsed = [] + normalized: list[str] = [] + for item in parsed: + feature = str(item or "").strip() + if feature in allowed_features and feature not in normalized: + normalized.append(feature) + return normalized or list(cls._DEFAULT_FEATURES_BY_PROFILE[menu_profile]) + async def _resolveLegacyTenantValue(self, *, RawValue: str, Source: str) -> TenantResolution: resolution = await self.TenantResolver.Resolve( RawValue=RawValue, diff --git a/fastapi_modules/fastapi_leaudit/services/impl/qichachaClient.py b/fastapi_modules/fastapi_leaudit/services/impl/qichachaClient.py new file mode 100644 index 0000000..d58ce92 --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/services/impl/qichachaClient.py @@ -0,0 +1,119 @@ +"""企查查 HTTP 客户端。""" + +from __future__ import annotations + +import asyncio +import hashlib +import time +from typing import Any + +import httpx + +from fastapi_admin.config import ( + QICHACHA_APP_KEY, + QICHACHA_BASE_URL, + QICHACHA_DISHONESTY_PATH, + QICHACHA_ENTERPRISE_PATH, + QICHACHA_MAX_RETRIES, + QICHACHA_RETRY_DELAY, + QICHACHA_SECRET_KEY, + QICHACHA_TIMEOUT, +) +from fastapi_common.fastapi_common_logger import logger +from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum +from fastapi_common.fastapi_common_web.exception.QichachaException import QichachaException + + +class QichachaClient: + """企查查 HTTP 客户端。""" + + def __init__( + self, + AppKey: str | None = None, + SecretKey: str | None = None, + BaseUrl: str | None = None, + EnterprisePath: str | None = None, + DishonestyPath: str | None = None, + Timeout: int | None = None, + MaxRetries: int | None = None, + RetryDelay: float | None = None, + ) -> None: + """初始化客户端配置。""" + self.AppKey = AppKey if AppKey is not None else str(QICHACHA_APP_KEY) + self.SecretKey = SecretKey if SecretKey is not None else str(QICHACHA_SECRET_KEY) + self.BaseUrl = (BaseUrl if BaseUrl is not None else str(QICHACHA_BASE_URL)).rstrip("/") + self.EnterprisePath = EnterprisePath if EnterprisePath is not None else str(QICHACHA_ENTERPRISE_PATH) + self.DishonestyPath = DishonestyPath if DishonestyPath is not None else str(QICHACHA_DISHONESTY_PATH) + self.Timeout = Timeout if Timeout is not None else int(QICHACHA_TIMEOUT) + self.MaxRetries = MaxRetries if MaxRetries is not None else int(QICHACHA_MAX_RETRIES) + self.RetryDelay = RetryDelay if RetryDelay is not None else float(QICHACHA_RETRY_DELAY) + + def BuildHeaders(self) -> dict[str, str]: + """生成企查查鉴权请求头。""" + timespan = str(int(time.time())) + token_source = f"{self.AppKey}{timespan}{self.SecretKey}" + token = hashlib.md5(token_source.encode("utf-8")).hexdigest().upper() + return {"Token": token, "Timespan": timespan} + + async def Request(self, Url: str, Params: dict[str, str]) -> dict[str, Any]: + """发送企查查 GET 请求并返回 JSON。""" + if not self.AppKey: + raise QichachaException(StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR, "企查查 APP_KEY 未配置") + if not self.SecretKey: + raise QichachaException(StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR, "企查查 SECRET_KEY 未配置") + + last_error: Exception | None = None + for attempt in range(max(self.MaxRetries, 1)): + try: + async with httpx.AsyncClient(timeout=self.Timeout) as client: + response = await client.get(Url, params=Params, headers=self.BuildHeaders()) + response.raise_for_status() + data = response.json() + if not isinstance(data, dict): + raise QichachaException(StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR, "企查查响应格式错误") + status = str(data.get("Status") or "") + if status and status not in {"200", "201"}: + message = str(data.get("Message") or "企查查查询失败") + raise QichachaException(StatusCodeEnum.HTTP_400_BAD_REQUEST, message) + return data + except QichachaException: + raise + except Exception as exc: + last_error = exc + if attempt < max(self.MaxRetries, 1) - 1: + await asyncio.sleep(self.RetryDelay) + + logger.error(f"企查查请求失败: url={Url}, error={last_error}") + raise QichachaException(StatusCodeEnum.HTTP_500_INTERNAL_SERVER_ERROR, f"企查查请求失败: {last_error}") + + async def GetEnterpriseInfo(self, Keyword: str) -> dict[str, Any] | None: + """查询企业工商信息。""" + data = await self.Request( + Url=f"{self.BaseUrl}{self.EnterprisePath}", + Params={"key": self.AppKey, "keyword": Keyword}, + ) + result = data.get("Result") + return result if isinstance(result, dict) else None + + async def GetDishonestyInfo(self, Keyword: str) -> dict[str, Any] | None: + """查询企业失信信息。""" + data = await self.Request( + Url=f"{self.BaseUrl}{self.DishonestyPath}", + Params={"key": self.AppKey, "searchKey": Keyword}, + ) + result = data.get("Result") + return result if isinstance(result, dict) else None + + async def QueryCompany(self, Keyword: str) -> tuple[dict[str, Any] | None, dict[str, Any] | None, str | None, str | None]: + """并发查询工商信息与失信信息。""" + enterprise_result, dishonesty_result = await asyncio.gather( + self.GetEnterpriseInfo(Keyword), + self.GetDishonestyInfo(Keyword), + ) + credit_code = ( + str(enterprise_result.get("CreditCode")) + if enterprise_result and enterprise_result.get("CreditCode") + else None + ) + company_name = str(enterprise_result.get("Name")) if enterprise_result and enterprise_result.get("Name") else None + return enterprise_result, dishonesty_result, credit_code, company_name diff --git a/fastapi_modules/fastapi_leaudit/services/impl/qichachaServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/qichachaServiceImpl.py new file mode 100644 index 0000000..8769733 --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/services/impl/qichachaServiceImpl.py @@ -0,0 +1,174 @@ +"""企查查服务实现。""" + +from __future__ import annotations + +from fastapi_admin.config import QICHACHA_CACHE_DAYS +from fastapi_common.fastapi_common_logger import logger +from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession +from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum +from fastapi_common.fastapi_common_web.exception.QichachaException import QichachaException +from fastapi_modules.fastapi_leaudit.domian.vo.qichachaVo import ( + QichachaBatchQueryVO, + QichachaCompanyQueryVO, + QichachaRecordStatusVO, +) +from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo +from fastapi_modules.fastapi_leaudit.services.impl.qichachaClient import QichachaClient +from fastapi_modules.fastapi_leaudit.services.impl.qichachaVoAssembler import QichachaVoAssembler +from fastapi_modules.fastapi_leaudit.services.qichachaService import IQichachaService + + +class QichachaServiceImpl(IQichachaService): + """企查查服务实现。""" + + def __init__(self, Client: QichachaClient | None = None, CacheDays: int | None = None) -> None: + """初始化企查查服务。""" + self.Client = Client if Client is not None else QichachaClient() + self.CacheDays = CacheDays if CacheDays is not None else int(QICHACHA_CACHE_DAYS) + + async def QueryCompany(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """查询企业完整信息。""" + keyword = Keyword.strip() + if not keyword: + raise QichachaException(StatusCodeEnum.HTTP_400_BAD_REQUEST, "查询关键词不能为空") + + async with GetAsyncSession() as session: + record = await QichachaCompanyInfo.FindByKeyword(session, keyword) + if record is not None and not ForceRefresh and QichachaCompanyInfo.GetAgeDays(record) <= self.CacheDays: + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + enterprise, dishonesty, credit_code, company_name = await self.Client.QueryCompany(keyword) + record = await QichachaCompanyInfo.Upsert( + session, + SearchKey=keyword, + CreditCode=credit_code, + CompanyName=company_name, + Enterprise=enterprise, + Dishonesty=dishonesty, + ) + logger.info(f"企查查企业信息已更新: {keyword}") + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + async def QueryEnterpriseOnly(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """仅查询企业工商信息。""" + keyword = Keyword.strip() + async with GetAsyncSession() as session: + record = await QichachaCompanyInfo.FindByKeyword(session, keyword) + if ( + record is not None + and record.enterprise is not None + and not ForceRefresh + and QichachaCompanyInfo.GetAgeDays(record) <= self.CacheDays + ): + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + enterprise = await self.Client.GetEnterpriseInfo(keyword) + credit_code = str(enterprise.get("CreditCode")) if enterprise and enterprise.get("CreditCode") else None + company_name = str(enterprise.get("Name")) if enterprise and enterprise.get("Name") else None + record = await QichachaCompanyInfo.Upsert( + session, + SearchKey=keyword, + CreditCode=credit_code, + CompanyName=company_name, + Enterprise=enterprise, + Dishonesty=record.dishonesty if record is not None else None, + ) + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + async def QueryDishonestyOnly(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """仅查询企业失信信息。""" + keyword = Keyword.strip() + async with GetAsyncSession() as session: + record = await QichachaCompanyInfo.FindByKeyword(session, keyword) + if ( + record is not None + and record.dishonesty is not None + and not ForceRefresh + and QichachaCompanyInfo.GetAgeDays(record) <= self.CacheDays + ): + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + dishonesty = await self.Client.GetDishonestyInfo(keyword) + record = await QichachaCompanyInfo.Upsert( + session, + SearchKey=keyword, + CreditCode=record.creditCode if record is not None else None, + CompanyName=record.companyName if record is not None else keyword, + Enterprise=record.enterprise if record is not None else None, + Dishonesty=dishonesty, + ) + return QichachaCompanyQueryVO( + success=True, + message="查询成功", + data=QichachaVoAssembler.BuildCompanyInfo(record), + ) + + async def BatchQuery(self, Keywords: list[str], ForceRefresh: bool = False) -> QichachaBatchQueryVO: + """批量查询企业信息。""" + results: list[QichachaCompanyQueryVO] = [] + for keyword in Keywords: + try: + results.append(await self.QueryCompany(keyword, ForceRefresh)) + except Exception as exc: + results.append( + QichachaCompanyQueryVO( + success=False, + message=str(exc), + data=None, + errorCode="QICHACHA_QUERY_FAILED", + ) + ) + success_count = len([item for item in results if item.success]) + return QichachaBatchQueryVO( + success=success_count == len(results), + total=len(results), + successCount=success_count, + failedCount=len(results) - success_count, + results=results, + ) + + async def GetRecordStatus(self, Keyword: str) -> QichachaRecordStatusVO: + """查询企业缓存状态。""" + keyword = Keyword.strip() + async with GetAsyncSession() as session: + record = await QichachaCompanyInfo.FindByKeyword(session, keyword) + if record is None: + return QichachaRecordStatusVO( + exists=False, + searchKey=keyword, + refreshThresholdDays=self.CacheDays, + needRefresh=True, + ) + age_days = QichachaCompanyInfo.GetAgeDays(record) + return QichachaRecordStatusVO( + exists=True, + searchKey=record.searchKey, + creditCode=record.creditCode, + companyName=record.companyName, + hasEnterprise=record.enterprise is not None, + hasDishonesty=record.dishonesty is not None, + updatedAt=QichachaVoAssembler.FormatDatetime(record.updated_at), + ageDays=age_days, + refreshThresholdDays=self.CacheDays, + needRefresh=age_days > self.CacheDays, + ) diff --git a/fastapi_modules/fastapi_leaudit/services/impl/qichachaVoAssembler.py b/fastapi_modules/fastapi_leaudit/services/impl/qichachaVoAssembler.py new file mode 100644 index 0000000..70d237d --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/services/impl/qichachaVoAssembler.py @@ -0,0 +1,40 @@ +"""企查查 VO 组装器。""" + +from __future__ import annotations + +from datetime import UTC +from typing import Any + +from fastapi_modules.fastapi_leaudit.domian.vo.qichachaVo import QichachaCompanyInfoVO +from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo + + +class QichachaVoAssembler: + """企查查 VO 组装器。""" + + @classmethod + def BuildCompanyInfo(cls, record: QichachaCompanyInfo) -> QichachaCompanyInfoVO: + """组装企业信息 VO。""" + dishonesty = record.dishonesty if isinstance(record.dishonesty, dict) else None + data_list = dishonesty.get("Data") if dishonesty else [] + has_dishonesty = bool(dishonesty and int(dishonesty.get("VerifyResult") or 0) == 1) + dishonesty_count = len(data_list) if isinstance(data_list, list) else 0 + return QichachaCompanyInfoVO( + searchKey=record.searchKey, + creditCode=record.creditCode, + companyName=record.companyName, + enterprise=record.enterprise if isinstance(record.enterprise, dict) else None, + dishonesty=dishonesty, + hasDishonesty=has_dishonesty, + dishonestyCount=dishonesty_count, + updatedAt=cls.FormatDatetime(record.updated_at), + ) + + @classmethod + def FormatDatetime(cls, value: Any) -> str | None: + """格式化时间。""" + if value is None: + return None + if getattr(value, "tzinfo", None) is None: + value = value.replace(tzinfo=UTC) + return value.isoformat() diff --git a/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py index 06461c4..8130d5e 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py @@ -135,6 +135,41 @@ class RbacAdminServiceImpl(IRbacAdminService): "is_cache": True, "meta": {"group": "cross-review"}, }, + { + "route_path": "/govdoc", + "route_name": "govdoc", + "component": "govdoc", + "route_title": "内部公文处理", + "icon": "ri-file-paper-2-line", + "sort_order": 65, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + }, + { + "route_path": "/govdoc/audits", + "route_name": "govdoc-audits", + "component": "govdoc.audits", + "route_title": "公文列表", + "icon": "ri-file-list-3-line", + "sort_order": 1, + "parent_path": "/govdoc", + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + }, + { + "route_path": "/govdoc/upload", + "route_name": "govdoc-upload", + "component": "govdoc.upload", + "route_title": "公文上传", + "icon": "ri-upload-cloud-line", + "sort_order": 2, + "parent_path": "/govdoc", + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + }, { "route_path": "/contract-template", "route_name": "contract-template", @@ -183,9 +218,9 @@ class RbacAdminServiceImpl(IRbacAdminService): "meta": {"group": "cross-review"}, }, { - "route_path": "/cross-checking/result", - "route_name": "cross-checking-result", - "component": "cross-checking.result", + "route_path": "/cross-checking/list", + "route_name": "cross-checking-list", + "component": "cross-checking.list", "route_title": "评查任务列表", "icon": "ri-file-list-3-line", "sort_order": 2, @@ -194,6 +229,18 @@ class RbacAdminServiceImpl(IRbacAdminService): "is_cache": True, "meta": {"group": "cross-review"}, }, + { + "route_path": "/cross-checking/result", + "route_name": "cross-checking-result", + "component": "cross-checking.result", + "route_title": "评查结果详情", + "icon": "ri-file-search-line", + "sort_order": 3, + "parent_path": "/cross-checking", + "is_hidden": True, + "is_cache": True, + "meta": {"group": "cross-review"}, + }, { "route_path": "/rules", "route_name": "rule-management", @@ -294,6 +341,16 @@ class RbacAdminServiceImpl(IRbacAdminService): {"permission_key": "rbac:tenants:create", "display_name": "创建租户", "module": "rbac", "resource": "tenants", "action": "create", "api_method": "POST", "api_path": "/api/v3/tenants", "route_path": "/tenants"}, {"permission_key": "rbac:tenants:update", "display_name": "更新租户", "module": "rbac", "resource": "tenants", "action": "update", "api_method": "PUT", "api_path": "/api/v3/tenants/{tenant_code}", "route_path": "/tenants"}, {"permission_key": "rbac:tenants:status", "display_name": "启停租户", "module": "rbac", "resource": "tenants", "action": "status", "api_method": "PATCH", "api_path": "/api/v3/tenants/{tenant_code}/status", "route_path": "/tenants"}, + {"permission_key": "govdoc:module:read", "display_name": "查看内部公文处理模块", "module": "govdoc", "resource": "module", "action": "read", "api_method": "GET", "api_path": "/api/govdoc", "route_path": "/govdoc"}, + {"permission_key": "govdoc:document:create", "display_name": "上传公文", "module": "govdoc", "resource": "document", "action": "create", "api_method": "POST", "api_path": "/api/govdoc/documents", "route_path": "/govdoc/upload"}, + {"permission_key": "govdoc:document:read", "display_name": "查看公文列表与详情", "module": "govdoc", "resource": "document", "action": "read", "api_method": "GET", "api_path": "/api/govdoc/documents", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:document:update", "display_name": "编辑公文", "module": "govdoc", "resource": "document", "action": "update", "api_method": "PATCH", "api_path": "/api/govdoc/documents/{document_id}", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:document:delete", "display_name": "删除公文", "module": "govdoc", "resource": "document", "action": "delete", "api_method": "DELETE", "api_path": "/api/govdoc/documents/{document_id}", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:run:create", "display_name": "发起公文格式审查", "module": "govdoc", "resource": "run", "action": "create", "api_method": "POST", "api_path": "/api/govdoc/runs", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:run:read", "display_name": "查看公文审查状态", "module": "govdoc", "resource": "run", "action": "read", "api_method": "GET", "api_path": "/api/govdoc/runs/{run_id}", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:report:read", "display_name": "下载公文审查报告", "module": "govdoc", "resource": "report", "action": "read", "api_method": "GET", "api_path": "/api/govdoc/runs/{run_id}/report", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:result:read", "display_name": "查看公文审查结果", "module": "govdoc", "resource": "result", "action": "read", "api_method": "GET", "api_path": "/api/govdoc/runs/{run_id}/result", "route_path": "/govdoc/audits"}, + {"permission_key": "govdoc:rule:read", "display_name": "查看公文规则", "module": "govdoc", "resource": "rule", "action": "read", "api_method": "GET", "api_path": "/api/govdoc/rules", "route_path": "/rules"}, {"permission_key": "usage_stats:overview:read", "display_name": "查看统计总览", "module": "usage_stats", "resource": "overview", "action": "read", "api_method": "GET", "api_path": "/api/v3/usage-stats/overview", "route_path": "/usage-stats"}, {"permission_key": "usage_stats:trends:read", "display_name": "查看统计趋势", "module": "usage_stats", "resource": "trends", "action": "read", "api_method": "GET", "api_path": "/api/v3/usage-stats/trends", "route_path": "/usage-stats"}, {"permission_key": "usage_stats:users:read", "display_name": "查看用户统计", "module": "usage_stats", "resource": "users", "action": "read", "api_method": "GET", "api_path": "/api/v3/usage-stats/by-users", "route_path": "/usage-stats"}, @@ -323,14 +380,9 @@ class RbacAdminServiceImpl(IRbacAdminService): {"permission_key": "rules:binding_create:write", "display_name": "创建规则绑定", "module": "rules", "resource": "binding_create", "action": "write", "api_method": "POST", "api_path": "/api/rule-sets/{rule_type}/bindings", "route_path": "/rules"}, {"permission_key": "rules:binding_update:write", "display_name": "更新规则绑定", "module": "rules", "resource": "binding_update", "action": "write", "api_method": "PUT", "api_path": "/api/rule-sets/bindings/{binding_id}", "route_path": "/rules"}, {"permission_key": "rules:binding_delete:delete", "display_name": "删除规则绑定", "module": "rules", "resource": "binding_delete", "action": "delete", "api_method": "DELETE", "api_path": "/api/rule-sets/bindings/{binding_id}", "route_path": "/rules"}, - {"permission_key": "evaluation_point:list:read", "display_name": "评查点列表", "module": "evaluation_point", "resource": "list", "action": "read", "api_method": "GET", "api_path": "/api/v3/evaluation-points", "route_path": "/rules"}, - {"permission_key": "evaluation_point:detail:read", "display_name": "评查点详情", "module": "evaluation_point", "resource": "detail", "action": "read", "api_method": "GET", "api_path": "/api/v3/evaluation-points/{id}", "route_path": "/rules"}, - {"permission_key": "evaluation_point:create:write", "display_name": "创建评查点", "module": "evaluation_point", "resource": "create", "action": "write", "api_method": "POST", "api_path": "/api/v3/evaluation-points", "route_path": "/rules"}, - {"permission_key": "evaluation_point:update:write", "display_name": "更新评查点", "module": "evaluation_point", "resource": "update", "action": "write", "api_method": "PUT", "api_path": "/api/v3/evaluation-points/{id}", "route_path": "/rules"}, - {"permission_key": "evaluation_point:delete:delete", "display_name": "删除评查点", "module": "evaluation_point", "resource": "delete", "action": "delete", "api_method": "DELETE", "api_path": "/api/v3/evaluation-points/{id}", "route_path": "/rules"}, {"permission_key": "cross_review:task:create", "display_name": "创建交叉评查任务", "module": "cross_review", "resource": "task", "action": "create", "api_method": "POST", "api_path": "/api/v3/cross-review/tasks", "route_path": "/cross-checking/upload"}, - {"permission_key": "cross_review:task:read", "display_name": "查看交叉评查任务", "module": "cross_review", "resource": "task", "action": "read", "api_method": "POST", "api_path": "/api/v3/cross-review/tasks/query", "route_path": "/cross-checking"}, - {"permission_key": "cross_review:progress:view", "display_name": "查看交叉评查任务进度", "module": "cross_review", "resource": "progress", "action": "view", "api_method": "GET", "api_path": "/api/v3/cross-review/tasks/{task_id}/progress", "route_path": "/cross-checking"}, + {"permission_key": "cross_review:task:read", "display_name": "查看交叉评查任务", "module": "cross_review", "resource": "task", "action": "read", "api_method": "POST", "api_path": "/api/v3/cross-review/tasks/query", "route_path": "/cross-checking/list"}, + {"permission_key": "cross_review:progress:view", "display_name": "查看交叉评查任务进度", "module": "cross_review", "resource": "progress", "action": "view", "api_method": "GET", "api_path": "/api/v3/cross-review/tasks/{task_id}/progress", "route_path": "/cross-checking/list"}, {"permission_key": "cross_review:document:read", "display_name": "查看交叉评查任务文档", "module": "cross_review", "resource": "document", "action": "read", "api_method": "GET", "api_path": "/api/v3/cross-review/tasks/{task_id}/documents", "route_path": "/cross-checking/result"}, {"permission_key": "cross_review:document:complete", "display_name": "确认交叉评查文档完成", "module": "cross_review", "resource": "document", "action": "complete", "api_method": "GET", "api_path": "/api/v3/cross-review/tasks/{task_id}/can-confirm", "route_path": "/cross-checking/result"}, {"permission_key": "cross_review:proposal:create", "display_name": "创建交叉评查提案", "module": "cross_review", "resource": "proposal", "action": "create", "api_method": "POST", "api_path": "/api/v3/cross-review/proposals", "route_path": "/cross-checking/result"}, @@ -357,12 +409,14 @@ class RbacAdminServiceImpl(IRbacAdminService): {"permission_key": "rag:dataset:create", "display_name": "创建知识库", "module": "rag", "resource": "dataset", "action": "create", "api_method": "POST", "api_path": "/api/v3/rag/datasets/admin", "route_path": "/chat-with-llm"}, {"permission_key": "rag:dataset:update", "display_name": "更新知识库与文档", "module": "rag", "resource": "dataset", "action": "update", "api_method": "PATCH", "api_path": "/api/v3/rag/datasets/{DatasetId}", "route_path": "/chat-with-llm"}, {"permission_key": "rag:dataset:delete", "display_name": "删除知识库与文档", "module": "rag", "resource": "dataset", "action": "delete", "api_method": "DELETE", "api_path": "/api/v3/rag/datasets/admin/{DatasetId}", "route_path": "/chat-with-llm"}, + {"permission_key": "qichacha:company:query", "display_name": "查询企业主体信息", "module": "qichacha", "resource": "company", "action": "query", "api_method": "POST", "api_path": "/api/v2/qichacha/company", "route_path": "/documents"}, + {"permission_key": "qichacha:status:read", "display_name": "查看企业主体缓存状态", "module": "qichacha", "resource": "status", "action": "read", "api_method": "GET", "api_path": "/api/v2/qichacha/status", "route_path": "/documents"}, ] _CORE_ROLE_AUTO_GRANTS: dict[str, tuple[str, ...]] = { - "super_admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status"), - "provincial_admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status"), - "admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status"), + "super_admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status", "qichacha:company:query", "qichacha:status:read"), + "provincial_admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status", "qichacha:company:query", "qichacha:status:read"), + "admin": ("rbac:user_tenant:update", "rbac:tenants:read", "rbac:tenants:create", "rbac:tenants:update", "rbac:tenants:status", "qichacha:company:query"), } async def ListRoles(self, CurrentUserId: int, Page: int, PageSize: int, RoleKey: str | None, RoleName: str | None, IncludeSystem: bool) -> RoleListVO: @@ -1393,28 +1447,15 @@ class RbacAdminServiceImpl(IRbacAdminService): if context["is_super_admin"] or not permissionKeys: return context - async with GetAsyncSession() as Session: - grantedRows = ( - await Session.execute( - text( - """ - SELECT DISTINCT p.permission_key - FROM role_permissions rp - JOIN permissions p ON p.id = rp.permission_id - JOIN user_role ur ON ur.role_id = rp.role_id - WHERE ur.user_id = :user_id - AND p.permission_key = ANY(:permission_keys) - AND rp.grant_type = 'GRANT' - """ - ).bindparams(permission_keys=permissionKeys), - {"user_id": CurrentUserId}, - ) - ).mappings().all() - granted = {str(row["permission_key"] or "") for row in grantedRows} - missing = [key for key in permissionKeys if key not in granted] - if not missing: - return context + deniedKeys = [] + permissionService = PermissionServiceImpl() + for permissionKey in permissionKeys: + if not await permissionService.CheckPermission(CurrentUserId, permissionKey): + deniedKeys.append(permissionKey) + if not deniedKeys: + return context + async with GetAsyncSession() as Session: displayRows = ( await Session.execute( text( @@ -1423,11 +1464,11 @@ class RbacAdminServiceImpl(IRbacAdminService): FROM permissions WHERE permission_key = ANY(:permission_keys) """ - ).bindparams(permission_keys=missing) + ).bindparams(permission_keys=deniedKeys) ) ).mappings().all() displayByKey = {str(row["permission_key"] or ""): str(row["display_name"] or "") for row in displayRows} - displayName = displayByKey.get(missing[0]) or missing[0] + displayName = displayByKey.get(deniedKeys[0]) or deniedKeys[0] raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, f"缺少「{displayName}」权限") async def _assertManageAndPermission(self, CurrentUserId: int, PermissionKey: str) -> dict[str, Any]: diff --git a/fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py index c2b082c..0565b0e 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/rbacServiceImpl.py @@ -33,6 +33,8 @@ class RbacServiceImpl(IRbacService): "/document-types", "/tenants", "/usage-stats", + "/govdoc", + "/govdoc-audit", ) _COMPAT_ROUTE_BLUEPRINTS: dict[str, list[dict[str, Any]]] = { @@ -110,24 +112,67 @@ class RbacServiceImpl(IRbacService): }, { "id": 1006, + "route_path": "/govdoc", + "route_name": "govdoc", + "component": "govdoc", + "parent_id": None, + "route_title": "内部公文处理", + "icon": "ri-file-paper-2-line", + "sort_order": 4, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": [ + { + "id": 1023, + "route_path": "/govdoc/audits", + "route_name": "govdoc-audits", + "component": "govdoc.audits", + "parent_id": 1006, + "route_title": "公文列表", + "icon": "ri-file-list-3-line", + "sort_order": 1, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": None, + }, + { + "id": 1024, + "route_path": "/govdoc/upload", + "route_name": "govdoc-upload", + "component": "govdoc.upload", + "parent_id": 1006, + "route_title": "公文上传", + "icon": "ri-upload-cloud-line", + "sort_order": 2, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": None, + }, + ], + }, + { + "id": 1007, "route_path": "/rules", "route_name": "rule-management", "component": "rules", "parent_id": None, "route_title": "规则管理", "icon": "ri-book-3-line", - "sort_order": 4, + "sort_order": 5, "is_hidden": False, "is_cache": True, "meta": {"group": "rules"}, "children": [ { "id": 1008, - "route_path": "/rules/list", + "route_path": "/rules", "route_name": "rules-list", - "component": "rules.list", - "parent_id": 1006, - "route_title": "评查点列表", + "component": "rules", + "parent_id": 1007, + "route_title": "规则配置列表", "icon": "ri-list-check-3", "sort_order": 2, "is_hidden": False, @@ -140,7 +185,7 @@ class RbacServiceImpl(IRbacService): "route_path": "/rules-files", "route_name": "rules-file", "component": "rules-files", - "parent_id": 1006, + "parent_id": 1007, "route_title": "评查文件列表", "icon": "ri-list-check-2", "sort_order": 3, @@ -159,7 +204,7 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "合同管理", "icon": "ri-file-search-line", - "sort_order": 5, + "sort_order": 6, "is_hidden": False, "is_cache": True, "meta": {"group": "contract"}, @@ -202,7 +247,7 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "系统设置", "icon": "ri-settings-4-line", - "sort_order": 6, + "sort_order": 7, "is_hidden": False, "is_cache": True, "meta": {"group": "settings"}, @@ -287,17 +332,17 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "交叉评查", "icon": "ri-color-filter-line", - "sort_order": 7, + "sort_order": 8, "is_hidden": False, "is_cache": True, "meta": {"group": "cross-review"}, "children": [ { - "id": 1019, + "id": 1020, "route_path": "/cross-checking/upload", "route_name": "cross-checking-upload", "component": "cross-checking.upload", - "parent_id": 1018, + "parent_id": 1019, "route_title": "创建任务", "icon": "ri-upload-cloud-line", "sort_order": 1, @@ -307,11 +352,11 @@ class RbacServiceImpl(IRbacService): "children": None, }, { - "id": 1020, - "route_path": "/cross-checking/result", - "route_name": "cross-checking-result", - "component": "cross-checking.result", - "parent_id": 1018, + "id": 1021, + "route_path": "/cross-checking/list", + "route_name": "cross-checking-list", + "component": "cross-checking.list", + "parent_id": 1019, "route_title": "评查任务列表", "icon": "ri-file-list-3-line", "sort_order": 2, @@ -320,6 +365,20 @@ class RbacServiceImpl(IRbacService): "meta": {"group": "cross-review"}, "children": None, }, + { + "id": 1022, + "route_path": "/cross-checking/result", + "route_name": "cross-checking-result", + "component": "cross-checking.result", + "parent_id": 1019, + "route_title": "评查结果详情", + "icon": "ri-file-search-line", + "sort_order": 3, + "is_hidden": True, + "is_cache": True, + "meta": {"group": "cross-review"}, + "children": None, + }, ], }, ], @@ -383,24 +442,67 @@ class RbacServiceImpl(IRbacService): }, { "id": 2005, + "route_path": "/govdoc", + "route_name": "govdoc", + "component": "govdoc", + "parent_id": None, + "route_title": "内部公文处理", + "icon": "ri-file-paper-2-line", + "sort_order": 4, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": [ + { + "id": 2019, + "route_path": "/govdoc/audits", + "route_name": "govdoc-audits", + "component": "govdoc.audits", + "parent_id": 2005, + "route_title": "公文列表", + "icon": "ri-file-list-3-line", + "sort_order": 1, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": None, + }, + { + "id": 2020, + "route_path": "/govdoc/upload", + "route_name": "govdoc-upload", + "component": "govdoc.upload", + "parent_id": 2005, + "route_title": "公文上传", + "icon": "ri-upload-cloud-line", + "sort_order": 2, + "is_hidden": False, + "is_cache": True, + "meta": {"group": "govdoc"}, + "children": None, + }, + ], + }, + { + "id": 2006, "route_path": "/rules", "route_name": "rule-management", "component": "rules", "parent_id": None, "route_title": "规则管理", "icon": "ri-book-3-line", - "sort_order": 4, + "sort_order": 5, "is_hidden": False, "is_cache": True, "meta": {"group": "rules"}, "children": [ { "id": 2007, - "route_path": "/rules/list", + "route_path": "/rules", "route_name": "rules-list", - "component": "rules.list", - "parent_id": 2005, - "route_title": "评查点列表", + "component": "rules", + "parent_id": 2006, + "route_title": "规则配置列表", "icon": "ri-list-check-3", "sort_order": 2, "is_hidden": False, @@ -413,7 +515,7 @@ class RbacServiceImpl(IRbacService): "route_path": "/rules-files", "route_name": "rules-file", "component": "rules-files", - "parent_id": 2005, + "parent_id": 2006, "route_title": "评查文件列表", "icon": "ri-list-check-2", "sort_order": 3, @@ -432,7 +534,7 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "合同管理", "icon": "ri-file-search-line", - "sort_order": 5, + "sort_order": 6, "is_hidden": False, "is_cache": True, "meta": {"group": "contract"}, @@ -475,7 +577,7 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "系统设置", "icon": "ri-settings-4-line", - "sort_order": 6, + "sort_order": 7, "is_hidden": False, "is_cache": True, "meta": {"group": "settings"}, @@ -518,7 +620,7 @@ class RbacServiceImpl(IRbacService): "parent_id": None, "route_title": "交叉评查", "icon": "ri-color-filter-line", - "sort_order": 7, + "sort_order": 8, "is_hidden": False, "is_cache": True, "meta": {"group": "cross-review"}, @@ -528,7 +630,7 @@ class RbacServiceImpl(IRbacService): "route_path": "/cross-checking/upload", "route_name": "cross-checking-upload", "component": "cross-checking.upload", - "parent_id": 2012, + "parent_id": 2015, "route_title": "创建任务", "icon": "ri-upload-cloud-line", "sort_order": 1, @@ -539,10 +641,10 @@ class RbacServiceImpl(IRbacService): }, { "id": 2017, - "route_path": "/cross-checking/result", - "route_name": "cross-checking-result", - "component": "cross-checking.result", - "parent_id": 2012, + "route_path": "/cross-checking/list", + "route_name": "cross-checking-list", + "component": "cross-checking.list", + "parent_id": 2015, "route_title": "评查任务列表", "icon": "ri-file-list-3-line", "sort_order": 2, @@ -551,6 +653,20 @@ class RbacServiceImpl(IRbacService): "meta": {"group": "cross-review"}, "children": None, }, + { + "id": 2018, + "route_path": "/cross-checking/result", + "route_name": "cross-checking-result", + "component": "cross-checking.result", + "parent_id": 2015, + "route_title": "评查结果详情", + "icon": "ri-file-search-line", + "sort_order": 3, + "is_hidden": True, + "is_cache": True, + "meta": {"group": "cross-review"}, + "children": None, + }, ], }, ], @@ -561,6 +677,9 @@ class RbacServiceImpl(IRbacService): "/files": ["documents:"], "/files/upload": ["documents:upload:"], "/documents": ["documents:"], + "/govdoc": ["govdoc:"], + "/govdoc/audits": ["govdoc:document:read"], + "/govdoc/upload": ["govdoc:document:create"], "/settings": ["entry_module:", "rbac:", "doc_type:"], "/entry-modules": ["entry_module:"], "/role-permissions": ["rbac:"], @@ -568,8 +687,14 @@ class RbacServiceImpl(IRbacService): "/tenants": ["rbac:tenants:"], "/usage-stats": ["usage_stats:"], "/rules": ["rules:", "evaluation_point:", "evaluation_group:"], - "/rules/list": ["rules:", "evaluation_point:"], "/rules-files": ["rules:"], + "/cross-checking": ["cross_review:"], + "/cross-checking/list": ["cross_review:task:", "cross_review:progress:"], + "/cross-checking/upload": ["cross_review:task:create"], + "/cross-checking/result": [ + "cross_review:document:", + "cross_review:proposal:", + ], } async def GetCurrentUserRoutes(self, UserId: int) -> RbacUserRoutesVO: diff --git a/fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py index fa881b3..3dbed7b 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py @@ -793,6 +793,7 @@ class RuleServiceImpl(IRuleService): await self._assert_document_type_access(Session, DocTypeId, current_user) GroupId = await self._resolve_unique_accessible_child_group_id(Session, DocTypeId, current_user) if GroupId is not None: + binding_scope = self._build_group_binding_scope_payload(current_user) ExistingGroupBinding = await Session.execute( text( """ @@ -800,11 +801,16 @@ class RuleServiceImpl(IRuleService): FROM leaudit_rule_group_bindings WHERE group_id = :group_id AND rule_set_id = :rule_set_id + AND COALESCE(NULLIF(BTRIM(tenant_code), ''), 'PROVINCIAL') = :tenant_code AND deleted_at IS NULL LIMIT 1 """ ), - {"group_id": GroupId, "rule_set_id": RuleSetId}, + { + "group_id": GroupId, + "rule_set_id": RuleSetId, + "tenant_code": binding_scope["tenant_code"], + }, ) if ExistingGroupBinding.mappings().first(): raise LeauditException(StatusCodeEnum.HTTP_409_CONFLICT, "该文档类型对应子组已绑定此规则集") @@ -815,6 +821,9 @@ class RuleServiceImpl(IRuleService): INSERT INTO leaudit_rule_group_bindings ( group_id, rule_set_id, + tenant_code, + scope_type, + tenant_name_snapshot, priority, is_active, note, @@ -823,6 +832,9 @@ class RuleServiceImpl(IRuleService): ) VALUES ( :group_id, :rule_set_id, + :tenant_code, + :scope_type, + :tenant_name_snapshot, :priority, true, :note, @@ -835,6 +847,9 @@ class RuleServiceImpl(IRuleService): { "group_id": GroupId, "rule_set_id": RuleSetId, + "tenant_code": binding_scope["tenant_code"], + "scope_type": binding_scope["scope_type"], + "tenant_name_snapshot": binding_scope["tenant_name_snapshot"], "priority": Priority, "note": Note, }, @@ -1177,6 +1192,23 @@ class RuleServiceImpl(IRuleService): "note": "由租户规则集派生自动补绑", } + def _build_group_binding_scope_payload(self, current_user: dict[str, object] | None) -> dict[str, object | None]: + if current_user and not current_user.get("is_global"): + tenant_code = normalize_scoped_tenant_code(str(current_user.get("tenant_code") or ""), default="") + if not tenant_code: + raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, "当前租户上下文缺失,不能绑定规则集") + return { + "tenant_code": tenant_code, + "scope_type": "TENANT", + "tenant_name_snapshot": str(current_user.get("tenant_name") or "").strip() or None, + } + + return { + "tenant_code": "PROVINCIAL", + "scope_type": "PROVINCIAL", + "tenant_name_snapshot": None, + } + async def _load_source_group_binding_ids(self, Session, source_rule_set_id: int) -> list[int]: if not await self._column_exists(Session, "leaudit_rule_group_bindings", "tenant_code"): return [] diff --git a/fastapi_modules/fastapi_leaudit/services/impl/usageStatsServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/usageStatsServiceImpl.py index 3dce801..286da83 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/usageStatsServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/usageStatsServiceImpl.py @@ -893,9 +893,7 @@ class UsageStatsServiceImpl(IUsageStatsService): } def _assert_stats_access(self, context: dict[str, Any]) -> None: - if context["is_global"] or context["can_manage"]: - return - raise LeauditException(StatusCodeEnum.HTTP_403_FORBIDDEN, "仅管理员可查看系统使用统计") + return def _build_user_scope_condition(self, context: dict[str, Any], filters: dict[str, Any], *, user_alias: str) -> tuple[str, dict[str, Any]]: conditions = ["1 = 1"] diff --git a/fastapi_modules/fastapi_leaudit/services/qichachaService.py b/fastapi_modules/fastapi_leaudit/services/qichachaService.py new file mode 100644 index 0000000..23d7176 --- /dev/null +++ b/fastapi_modules/fastapi_leaudit/services/qichachaService.py @@ -0,0 +1,40 @@ +"""企查查服务接口。""" + +from __future__ import annotations + +from abc import ABC, abstractmethod + +from fastapi_modules.fastapi_leaudit.domian.vo.qichachaVo import ( + QichachaBatchQueryVO, + QichachaCompanyQueryVO, + QichachaRecordStatusVO, +) + + +class IQichachaService(ABC): + """企查查服务接口。""" + + @abstractmethod + async def QueryCompany(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """查询企业完整信息。""" + ... + + @abstractmethod + async def QueryEnterpriseOnly(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """仅查询企业工商信息。""" + ... + + @abstractmethod + async def QueryDishonestyOnly(self, Keyword: str, ForceRefresh: bool = False) -> QichachaCompanyQueryVO: + """仅查询企业失信信息。""" + ... + + @abstractmethod + async def BatchQuery(self, Keywords: list[str], ForceRefresh: bool = False) -> QichachaBatchQueryVO: + """批量查询企业信息。""" + ... + + @abstractmethod + async def GetRecordStatus(self, Keyword: str) -> QichachaRecordStatusVO: + """查询企业缓存状态。""" + ... diff --git a/legal-platform-frontend b/legal-platform-frontend index 1abbbe6..40ef991 160000 --- a/legal-platform-frontend +++ b/legal-platform-frontend @@ -1 +1 @@ -Subproject commit 1abbbe6b4eaff963339bc3c1e22f71c7da728e77 +Subproject commit 40ef991434f4890382f32ed6146e0ef076cf53fa diff --git a/scripts/创建sql/entry_module_menu_profile_migration.sql b/scripts/创建sql/entry_module_menu_profile_migration.sql new file mode 100644 index 0000000..da8fc03 --- /dev/null +++ b/scripts/创建sql/entry_module_menu_profile_migration.sql @@ -0,0 +1,67 @@ +-- 入口模块菜单模板、功能清单、文档入口归属迁移脚本 +-- 目标: +-- 1. 入口模块用 menu_profile/features 控制左侧菜单,不再靠名称包含“合同/公文”判断。 +-- 2. 文档记录补 entry_module_id,后续列表、上传、统计、质量校验可以按入口模块过滤。 +-- 3. 二级分组增加父级内文档类型唯一约束,避免规则命中不稳定。 + +BEGIN; + +ALTER TABLE leaudit_entry_modules +ADD COLUMN IF NOT EXISTS menu_profile VARCHAR(64) NOT NULL DEFAULT 'document_review', +ADD COLUMN IF NOT EXISTS features JSONB NOT NULL DEFAULT '[]'::jsonb; + +ALTER TABLE leaudit_documents +ADD COLUMN IF NOT EXISTS entry_module_id BIGINT NULL REFERENCES leaudit_entry_modules(id); + +CREATE INDEX IF NOT EXISTS idx_leaudit_entry_modules_menu_profile +ON leaudit_entry_modules(menu_profile) +WHERE deleted_at IS NULL; + +CREATE INDEX IF NOT EXISTS idx_leaudit_documents_entry_module_id +ON leaudit_documents(entry_module_id); + +CREATE UNIQUE INDEX IF NOT EXISTS uq_leaudit_ep_groups_parent_doc_type_active +ON leaudit_evaluation_point_groups(pid, document_type_id) +WHERE deleted_at IS NULL + AND COALESCE(pid, 0) <> 0 + AND document_type_id IS NOT NULL; + +UPDATE leaudit_entry_modules +SET + menu_profile = CASE + WHEN path IN ('/govdoc/audits', '/govdoc', '/govdoc-audit') THEN 'govdoc' + WHEN path IN ('/contract-template', '/contract-template/list', '/contract-template/search') THEN 'contract' + ELSE COALESCE(NULLIF(menu_profile, ''), 'document_review') + END, + features = CASE + WHEN path IN ('/govdoc/audits', '/govdoc', '/govdoc-audit') + THEN '["home","govdoc_audits","govdoc_upload","rule_groups"]'::jsonb + WHEN path IN ('/contract-template', '/contract-template/list', '/contract-template/search') + THEN '["home","documents","upload","rules","contract_template_search","contract_template_list"]'::jsonb + WHEN features IS NULL OR features = '[]'::jsonb + THEN '["home","documents","upload","rules","rule_groups"]'::jsonb + ELSE features + END +WHERE deleted_at IS NULL; + +UPDATE leaudit_documents d +SET entry_module_id = COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) +FROM leaudit_document_types dt +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 +WHERE d.type_id = dt.id + AND d.entry_module_id IS NULL; + +COMMIT; + +-- 验证入口模块菜单字段: +-- SELECT id, name, path, menu_profile, features +-- FROM leaudit_entry_modules +-- WHERE deleted_at IS NULL +-- ORDER BY sort_order, id; + +-- 验证仍未回填入口模块归属的文档: +-- SELECT COUNT(*) AS documents_without_entry_module +-- FROM leaudit_documents +-- WHERE deleted_at IS NULL +-- AND entry_module_id IS NULL; diff --git a/scripts/创建sql/rbac_entry_module_super_admin_only.sql b/scripts/创建sql/rbac_entry_module_super_admin_only.sql new file mode 100644 index 0000000..6ba20ff --- /dev/null +++ b/scripts/创建sql/rbac_entry_module_super_admin_only.sql @@ -0,0 +1,66 @@ +-- ============================================================================ +-- 入口模块管理权限收口:仅系统超级管理员维护入口模块 +-- 说明: +-- 1. 不在代码里硬编码角色名,运行时仍然只认 RBAC 权限点。 +-- 2. 本脚本只调整默认 RBAC 数据,把 admin / provincial_admin 的入口模块管理能力移除。 +-- 3. 若后续确需给某个角色开放入口模块管理,请通过角色权限页面重新分配。 +-- 4. 可重复执行。 +-- ============================================================================ + +BEGIN; + +-- 保证系统超级管理员拥有入口模块路由。 +INSERT INTO role_route (role_id, route_id, permission, status, created_at, updated_at) +SELECT r.id, sr.id, 'RW', 1, NOW(), NOW() +FROM roles r +JOIN sys_routes sr ON sr.route_path = '/entry-modules' AND sr.deleted_at IS NULL +WHERE r.role_key = 'super_admin' +ON CONFLICT (role_id, route_id) DO UPDATE SET + permission = EXCLUDED.permission, + status = EXCLUDED.status, + updated_at = NOW(); + +-- 保证系统超级管理员拥有入口模块全部权限点。 +INSERT INTO role_permissions (role_id, permission_id, grant_type, data_scope, created_at, updated_at) +SELECT r.id, p.id, 'GRANT', 'ALL', NOW(), NOW() +FROM roles r +JOIN permissions p ON p.permission_key LIKE 'entry_module:%' +WHERE r.role_key = 'super_admin' +ON CONFLICT (role_id, permission_id) DO UPDATE SET + grant_type = EXCLUDED.grant_type, + data_scope = EXCLUDED.data_scope, + updated_at = NOW(); + +-- 移除地区管理员 / 旧省级管理员的入口模块权限点。 +DELETE FROM role_permissions rp +USING roles r, permissions p +WHERE rp.role_id = r.id + AND rp.permission_id = p.id + AND r.role_key IN ('admin', 'provincial_admin') + AND p.permission_key LIKE 'entry_module:%'; + +-- 移除地区管理员 / 旧省级管理员的入口模块管理菜单。 +DELETE FROM role_route rr +USING roles r, sys_routes sr +WHERE rr.role_id = r.id + AND rr.route_id = sr.id + AND r.role_key IN ('admin', 'provincial_admin') + AND sr.route_path = '/entry-modules'; + +COMMIT; + +-- 验证结果:应只看到 super_admin 拥有入口模块权限。 +SELECT r.role_key, p.permission_key +FROM roles r +JOIN role_permissions rp ON rp.role_id = r.id +JOIN permissions p ON p.id = rp.permission_id +WHERE p.permission_key LIKE 'entry_module:%' +ORDER BY r.role_key, p.permission_key; + +-- 验证结果:admin / provincial_admin 不应再拥有 /entry-modules 路由。 +SELECT r.role_key, sr.route_path, rr.permission, rr.status +FROM roles r +JOIN role_route rr ON rr.role_id = r.id +JOIN sys_routes sr ON sr.id = rr.route_id +WHERE sr.route_path = '/entry-modules' +ORDER BY r.role_key; diff --git a/scripts/创建sql/repair_entry_module_scope_data_20260524.sql b/scripts/创建sql/repair_entry_module_scope_data_20260524.sql new file mode 100644 index 0000000..9bc55d2 --- /dev/null +++ b/scripts/创建sql/repair_entry_module_scope_data_20260524.sql @@ -0,0 +1,145 @@ +-- 修复入口模块归属历史数据 +-- 执行目标: +-- 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 diff --git a/scripts/创建sql/repair_govdoc_sample_entry_module_20260524.sql b/scripts/创建sql/repair_govdoc_sample_entry_module_20260524.sql new file mode 100644 index 0000000..30ea59c --- /dev/null +++ b/scripts/创建sql/repair_govdoc_sample_entry_module_20260524.sql @@ -0,0 +1,15 @@ +-- 回填旧公文示例文档入口归属 +-- 这 3 条是旧 govdoc 链路数据,只补 entry_module_id,不伪造 type_id/group_id。 + +BEGIN; + +UPDATE leaudit_documents +SET entry_module_id = 3, + updated_at = NOW() +WHERE id IN (46, 47, 48) + AND deleted_at IS NULL + AND entry_module_id IS NULL + AND engine_type = 'govdoc' + AND review_scope = 'govdoc'; + +COMMIT; diff --git a/scripts/创建sql/schema_qichacha_company_info.sql b/scripts/创建sql/schema_qichacha_company_info.sql new file mode 100644 index 0000000..5358076 --- /dev/null +++ b/scripts/创建sql/schema_qichacha_company_info.sql @@ -0,0 +1,36 @@ +-- 企查查企业主体信息缓存表。 + +CREATE TABLE IF NOT EXISTS qcc_company_info ( + id BIGSERIAL PRIMARY KEY, + search_key VARCHAR(200) NOT NULL, + credit_code VARCHAR(64), + company_name VARCHAR(255), + enterprise JSONB, + dishonesty JSONB, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMPTZ +); + +CREATE UNIQUE INDEX IF NOT EXISTS idx_qcc_company_search_key + ON qcc_company_info (search_key) + WHERE deleted_at IS NULL; + +CREATE INDEX IF NOT EXISTS idx_qcc_company_credit_code + ON qcc_company_info (credit_code) + WHERE deleted_at IS NULL; + +CREATE INDEX IF NOT EXISTS idx_qcc_company_name + ON qcc_company_info (company_name) + WHERE deleted_at IS NULL; + +CREATE INDEX IF NOT EXISTS idx_qcc_company_created_at + ON qcc_company_info (created_at) + WHERE deleted_at IS NULL; + +COMMENT ON TABLE qcc_company_info IS '企查查企业主体信息缓存表'; +COMMENT ON COLUMN qcc_company_info.search_key IS '原始查询关键词'; +COMMENT ON COLUMN qcc_company_info.credit_code IS '统一社会信用代码'; +COMMENT ON COLUMN qcc_company_info.company_name IS '企业名称'; +COMMENT ON COLUMN qcc_company_info.enterprise IS '企查查工商信息原始响应 Result'; +COMMENT ON COLUMN qcc_company_info.dishonesty IS '企查查失信核查原始响应 Result'; diff --git a/scripts/创建sql/seed_govdoc_entry_module.sql b/scripts/创建sql/seed_govdoc_entry_module.sql index 47f036f..858727f 100644 --- a/scripts/创建sql/seed_govdoc_entry_module.sql +++ b/scripts/创建sql/seed_govdoc_entry_module.sql @@ -6,7 +6,7 @@ -- 3. 兼容历史库中 entry_modules 时间字段命名差异 -- -- 说明: --- - 当前模块入口统一收口到 /govdoc/list,与模块路由 seed 保持一致。 +-- - 当前模块入口统一收口到 /govdoc/audits,与前端真实列表路由保持一致。 -- - 若后续前端改成其他入口页,请同步更新本脚本中的 v_target_path。 -- - 页面访问权限与左侧菜单路由仍依赖 sys_routes / role_route, -- 这部分建议由配套脚本 seed_govdoc_routes.sql 单独维护。 @@ -18,7 +18,7 @@ DO $$ DECLARE v_name text := '内部公文'; v_description text := '内部公文处理与格式审查入口'; - v_target_path text := '/govdoc/list'; + v_target_path text := '/govdoc/audits'; v_icon_path text := 'documents/mz/static/img/entry_module_3.png'; v_sort_order integer := 30; v_areas jsonb := '[ diff --git a/scripts/创建sql/seed_govdoc_routes.sql b/scripts/创建sql/seed_govdoc_routes.sql index 4727efd..494c0ba 100644 --- a/scripts/创建sql/seed_govdoc_routes.sql +++ b/scripts/创建sql/seed_govdoc_routes.sql @@ -103,16 +103,16 @@ VALUES NULL ), ( - '/govdoc/list', - 'govdoc.list', - 'govdoc.list', + '/govdoc/audits', + 'govdoc.audits', + 'govdoc.audits', (SELECT id FROM root_route), '公文列表', 'ri-file-list-3-line', 2, FALSE, TRUE, - '{"group":"govdoc","module":"govdoc","page":"list"}'::jsonb, + '{"group":"govdoc","module":"govdoc","page":"audits"}'::jsonb, 0, NOW(), NOW(), @@ -187,7 +187,7 @@ SET parent_id = root.id, route_title = CASE WHEN child.route_path = '/govdoc/upload' THEN '上传公文' - WHEN child.route_path = '/govdoc/list' THEN '公文列表' + WHEN child.route_path = '/govdoc/audits' THEN '公文列表' WHEN child.route_path = '/govdoc/detail' THEN '公文详情' WHEN child.route_path = '/govdoc/rules' THEN '规则配置' WHEN child.route_path = '/govdoc/settings' THEN '模块配置' @@ -204,7 +204,7 @@ WHERE child.deleted_at IS NULL AND root.route_path = '/govdoc' AND child.route_path IN ( '/govdoc/upload', - '/govdoc/list', + '/govdoc/audits', '/govdoc/detail', '/govdoc/rules', '/govdoc/settings' @@ -229,7 +229,7 @@ route_map AS ( AND route_path IN ( '/govdoc', '/govdoc/upload', - '/govdoc/list', + '/govdoc/audits', '/govdoc/detail', '/govdoc/rules', '/govdoc/settings' @@ -239,27 +239,27 @@ seed(role_key, route_path, permission, status) AS ( VALUES ('super_admin', '/govdoc', 'RW', 1), ('super_admin', '/govdoc/upload', 'RW', 1), - ('super_admin', '/govdoc/list', 'RW', 1), + ('super_admin', '/govdoc/audits', 'RW', 1), ('super_admin', '/govdoc/detail', 'RW', 1), ('super_admin', '/govdoc/rules', 'RW', 1), ('super_admin', '/govdoc/settings', 'RW', 1), ('provincial_admin', '/govdoc', 'RW', 1), ('provincial_admin', '/govdoc/upload', 'RW', 1), - ('provincial_admin', '/govdoc/list', 'RW', 1), + ('provincial_admin', '/govdoc/audits', 'RW', 1), ('provincial_admin', '/govdoc/detail', 'RW', 1), ('provincial_admin', '/govdoc/rules', 'RW', 1), ('provincial_admin', '/govdoc/settings', 'RW', 1), ('admin', '/govdoc', 'RW', 1), ('admin', '/govdoc/upload', 'RW', 1), - ('admin', '/govdoc/list', 'RW', 1), + ('admin', '/govdoc/audits', 'RW', 1), ('admin', '/govdoc/detail', 'RW', 1), ('admin', '/govdoc/rules', 'R', 1), ('common', '/govdoc', 'R', 1), ('common', '/govdoc/upload', 'R', 1), - ('common', '/govdoc/list', 'R', 1), + ('common', '/govdoc/audits', 'R', 1), ('common', '/govdoc/detail', 'R', 1), ('common', '/govdoc/rules', 'R', 1) ) diff --git a/scripts/创建sql/user_rbac_seed.sql b/scripts/创建sql/user_rbac_seed.sql index f989335..a6776dd 100644 --- a/scripts/创建sql/user_rbac_seed.sql +++ b/scripts/创建sql/user_rbac_seed.sql @@ -91,11 +91,6 @@ VALUES ('rules:binding_create:write', 'rules', 'binding_create', 'write', '创建规则绑定', '创建规则绑定', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 49, NULL, '/api/rule-sets/{rule_type}/bindings', 'POST', NULL), ('rules:binding_update:write', 'rules', 'binding_update', 'write', '更新规则绑定', '更新规则绑定', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 50, NULL, '/api/rule-sets/bindings/{binding_id}', 'PUT', NULL), ('rules:binding_delete:delete', 'rules', 'binding_delete', 'delete', '删除规则绑定', '删除规则绑定', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 51, NULL, '/api/rule-sets/bindings/{binding_id}', 'DELETE', NULL), - ('evaluation_point:list:read', 'evaluation_point', 'list', 'read', '查看评查点列表', '评查点列表', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 52, NULL, '/api/v3/evaluation-points', 'GET', NULL), - ('evaluation_point:detail:read', 'evaluation_point', 'detail', 'read', '查看评查点详情', '评查点详情', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 53, NULL, '/api/v3/evaluation-points/{id}', 'GET', NULL), - ('evaluation_point:create:write', 'evaluation_point', 'create', 'write', '创建评查点', '创建评查点', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 54, NULL, '/api/v3/evaluation-points', 'POST', NULL), - ('evaluation_point:update:write', 'evaluation_point', 'update', 'write', '更新评查点', '更新评查点', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 55, NULL, '/api/v3/evaluation-points/{id}', 'PUT', NULL), - ('evaluation_point:delete:delete', 'evaluation_point', 'delete', 'delete', '删除评查点', '删除评查点', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 56, NULL, '/api/v3/evaluation-points/{id}', 'DELETE', NULL), ('cross_review:task:create', 'cross_review', 'task', 'create', '创建交叉评查任务', '创建交叉评查任务', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 57, NULL, '/api/v3/cross-review/tasks', 'POST', NULL), ('cross_review:task:read', 'cross_review', 'task', 'read', '查看交叉评查任务', '查看交叉评查任务', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 58, NULL, '/api/v3/cross-review/tasks/query', 'POST', NULL), ('cross_review:progress:view', 'cross_review', 'progress', 'view', '查看交叉评查任务进度', '查看交叉评查任务进度', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 59, NULL, '/api/v3/cross-review/tasks/{task_id}/progress', 'GET', NULL), @@ -124,7 +119,9 @@ VALUES ('rag:conversation:delete', 'rag', 'conversation', 'delete', '删除 RAG 会话', '删除 RAG 会话', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 89, NULL, '/api/v3/rag/chat/conversations/{ConversationId}', 'DELETE', NULL), ('rag:message:feedback', 'rag', 'message', 'feedback', '反馈 RAG 消息', '反馈 RAG 消息', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 90, NULL, '/api/v3/rag/chat/messages/{MessageId}/feedback', 'POST', NULL), ('rag:dataset:read', 'rag', 'dataset', 'read', '查看 RAG 知识库', '查看 RAG 知识库', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 91, NULL, '/api/v3/rag/datasets/my', 'GET', NULL), - ('document:document:update', 'document', 'document', 'update', '修改文档基本信息', '修改文档', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 92, NULL, '/api/documents/edit', 'POST', NULL) + ('document:document:update', 'document', 'document', 'update', '修改文档基本信息', '修改文档', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 92, NULL, '/api/documents/edit', 'POST', NULL), + ('qichacha:company:query', 'qichacha', 'company', 'query', '查询企业主体信息', '查询企业主体信息', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 93, NULL, '/api/v2/qichacha/company', 'POST', NULL), + ('qichacha:status:read', 'qichacha', 'status', 'read', '查看企业主体缓存状态', '查看企业主体缓存状态', 'API', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL, NULL, 94, NULL, '/api/v2/qichacha/status', 'GET', NULL) ON CONFLICT (permission_key) DO UPDATE SET module = EXCLUDED.module, resource = EXCLUDED.resource, @@ -245,11 +242,6 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('super_admin', 'rules:binding_create:write', 'GRANT', 'ALL'), ('super_admin', 'rules:binding_update:write', 'GRANT', 'ALL'), ('super_admin', 'rules:binding_delete:delete', 'GRANT', 'ALL'), - ('super_admin', 'evaluation_point:list:read', 'GRANT', 'ALL'), - ('super_admin', 'evaluation_point:detail:read', 'GRANT', 'ALL'), - ('super_admin', 'evaluation_point:create:write', 'GRANT', 'ALL'), - ('super_admin', 'evaluation_point:update:write', 'GRANT', 'ALL'), - ('super_admin', 'evaluation_point:delete:delete', 'GRANT', 'ALL'), ('super_admin', 'cross_review:task:create', 'GRANT', 'ALL'), ('super_admin', 'cross_review:task:read', 'GRANT', 'ALL'), ('super_admin', 'cross_review:progress:view', 'GRANT', 'ALL'), @@ -276,6 +268,8 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('super_admin', 'rbac:permissions:read', 'GRANT', 'ALL'), ('super_admin', 'rbac:role_permissions:write', 'GRANT', 'ALL'), ('super_admin', 'rbac:role_routes:write', 'GRANT', 'ALL'), + ('super_admin', 'qichacha:company:query', 'GRANT', 'ALL'), + ('super_admin', 'qichacha:status:read', 'GRANT', 'ALL'), ('provincial_admin', 'auth:me:read', 'GRANT', 'ALL'), ('provincial_admin', 'documents:upload:write', 'GRANT', 'ALL'), @@ -298,11 +292,6 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('provincial_admin', 'rules:binding_create:write', 'GRANT', 'ALL'), ('provincial_admin', 'rules:binding_update:write', 'GRANT', 'ALL'), ('provincial_admin', 'rules:binding_delete:delete', 'GRANT', 'ALL'), - ('provincial_admin', 'evaluation_point:list:read', 'GRANT', 'ALL'), - ('provincial_admin', 'evaluation_point:detail:read', 'GRANT', 'ALL'), - ('provincial_admin', 'evaluation_point:create:write', 'GRANT', 'ALL'), - ('provincial_admin', 'evaluation_point:update:write', 'GRANT', 'ALL'), - ('provincial_admin', 'evaluation_point:delete:delete', 'GRANT', 'ALL'), ('provincial_admin', 'cross_review:task:create', 'GRANT', 'ALL'), ('provincial_admin', 'cross_review:task:read', 'GRANT', 'ALL'), ('provincial_admin', 'cross_review:progress:view', 'GRANT', 'ALL'), @@ -329,6 +318,8 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('provincial_admin', 'rbac:permissions:read', 'GRANT', 'ALL'), ('provincial_admin', 'rbac:role_permissions:write', 'GRANT', 'ALL'), ('provincial_admin', 'rbac:role_routes:write', 'GRANT', 'ALL'), + ('provincial_admin', 'qichacha:company:query', 'GRANT', 'ALL'), + ('provincial_admin', 'qichacha:status:read', 'GRANT', 'ALL'), ('admin', 'auth:me:read', 'GRANT', 'DEPT'), ('admin', 'documents:upload:write', 'GRANT', 'DEPT'), @@ -360,11 +351,6 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('admin', 'cross_review:proposal:read', 'GRANT', 'DEPT'), ('admin', 'cross_review:proposal:delete', 'GRANT', 'DEPT'), ('admin', 'cross_review:proposal:vote', 'GRANT', 'DEPT'), - ('admin', 'evaluation_point:list:read', 'GRANT', 'DEPT'), - ('admin', 'evaluation_point:detail:read', 'GRANT', 'DEPT'), - ('admin', 'evaluation_point:create:write', 'GRANT', 'DEPT'), - ('admin', 'evaluation_point:update:write', 'GRANT', 'DEPT'), - ('admin', 'evaluation_point:delete:delete', 'GRANT', 'DEPT'), ('admin', 'rag:app:read', 'GRANT', 'DEPT'), ('admin', 'rag:chat:use', 'GRANT', 'DEPT'), ('admin', 'rag:conversation:read', 'GRANT', 'DEPT'), @@ -374,6 +360,7 @@ seed(role_key, permission_key, grant_type, data_scope) AS ( ('admin', 'rag:dataset:read', 'GRANT', 'DEPT'), ('admin', 'users:list:read', 'GRANT', 'DEPT'), ('admin', 'users:update:write', 'GRANT', 'DEPT'), + ('admin', 'qichacha:company:query', 'GRANT', 'DEPT'), ('common', 'auth:me:read', 'GRANT', 'SELF'), ('common', 'documents:upload:write', 'GRANT', 'SELF'), diff --git a/scripts/创建sql/verify_entry_module_menu_profile.sql b/scripts/创建sql/verify_entry_module_menu_profile.sql new file mode 100644 index 0000000..27cacac --- /dev/null +++ b/scripts/创建sql/verify_entry_module_menu_profile.sql @@ -0,0 +1,209 @@ +-- 入口模块菜单模板、多租户可见性、文档归属巡检脚本 +-- 用途: +-- 1. 检查 entry_module_menu_profile_migration.sql 是否补齐字段、索引、默认值。 +-- 2. 检查入口模块 features/menu_profile 是否存在非法值或空配置。 +-- 3. 检查文档 entry_module_id 回填情况和二级分组重复风险。 +-- 4. 本脚本只查询,不修改数据。 +-- +-- 推荐执行方式: +-- psql "$DATABASE_URL" -f scripts/创建sql/verify_entry_module_menu_profile.sql + +-- ========================================================= +-- 1. 必要字段检查 +-- ========================================================= +SELECT + table_name, + column_name, + data_type, + is_nullable, + column_default +FROM information_schema.columns +WHERE table_schema = current_schema() + AND ( + (table_name = 'leaudit_entry_modules' AND column_name IN ('menu_profile', 'features')) + OR (table_name = 'leaudit_documents' AND column_name = 'entry_module_id') + ) +ORDER BY table_name, column_name; + +-- ========================================================= +-- 2. 必要索引检查 +-- ========================================================= +SELECT + schemaname, + tablename, + indexname, + indexdef +FROM pg_indexes +WHERE schemaname = current_schema() + AND indexname IN ( + 'idx_leaudit_entry_modules_menu_profile', + 'idx_leaudit_documents_entry_module_id', + 'uq_leaudit_ep_groups_parent_doc_type_active' + ) +ORDER BY indexname; + +-- ========================================================= +-- 3. 入口模块菜单配置总览 +-- ========================================================= +SELECT + em.id, + em.name, + em.path, + em.menu_profile, + em.features, + em.is_enabled, + COALESCE( + STRING_AGG(emt.tenant_code, ', ' ORDER BY emt.tenant_code) + FILTER (WHERE emt.is_enabled IS TRUE), + '' + ) AS enabled_tenants +FROM leaudit_entry_modules em +LEFT JOIN leaudit_entry_module_tenants emt + ON emt.entry_module_id = em.id +WHERE em.deleted_at IS NULL +GROUP BY em.id, em.name, em.path, em.menu_profile, em.features, em.is_enabled +ORDER BY em.sort_order, em.id; + +-- ========================================================= +-- 4. 非法 menu_profile 检查:结果应为空 +-- ========================================================= +SELECT + id, + name, + path, + menu_profile +FROM leaudit_entry_modules +WHERE deleted_at IS NULL + AND menu_profile NOT IN ('document_review', 'contract', 'govdoc', 'cross_checking', 'custom') +ORDER BY id; + +-- ========================================================= +-- 5. 空 features 检查:结果应为空或只包含刻意关闭菜单的入口 +-- ========================================================= +SELECT + id, + name, + path, + menu_profile, + features +FROM leaudit_entry_modules +WHERE deleted_at IS NULL + AND ( + features IS NULL + OR jsonb_typeof(features) <> 'array' + OR jsonb_array_length(features) = 0 + ) +ORDER BY id; + +-- ========================================================= +-- 6. 非法 feature 编码检查:结果应为空 +-- ========================================================= +SELECT + em.id, + em.name, + em.menu_profile, + invalid_feature.feature +FROM leaudit_entry_modules em +CROSS JOIN LATERAL jsonb_array_elements_text(em.features) AS invalid_feature(feature) +WHERE em.deleted_at IS NULL + AND invalid_feature.feature NOT IN ( + 'home', + 'documents', + 'upload', + 'rules', + 'rule_groups', + 'contract_template_search', + 'contract_template_list', + 'govdoc_audits', + 'govdoc_upload', + 'cross_checking', + 'cross_checking_upload', + 'cross_checking_list', + 'usage_stats' + ) +ORDER BY em.id, invalid_feature.feature; + +-- ========================================================= +-- 7. 文档归属缺失检查 +-- ========================================================= +SELECT + COUNT(*) AS documents_without_entry_module +FROM leaudit_documents +WHERE deleted_at IS NULL + AND entry_module_id IS NULL; + +SELECT + d.id, + d.normalized_name AS document_name, + d.type_id, + dt.name AS document_type_name, + d.group_id, + g.name AS group_name, + d.tenant_code, + d.created_at +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 +WHERE d.deleted_at IS NULL + AND d.entry_module_id IS NULL +ORDER BY d.created_at DESC NULLS LAST, d.id DESC +LIMIT 50; + +-- ========================================================= +-- 8. 文档 entry_module_id 与分组/文档类型推导不一致检查 +-- ========================================================= +SELECT + d.id, + d.normalized_name AS document_name, + d.entry_module_id AS document_entry_module_id, + COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) AS resolved_entry_module_id, + d.type_id, + d.group_id, + d.tenant_code +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 +WHERE d.deleted_at IS NULL + AND d.entry_module_id IS NOT NULL + AND COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) IS NOT NULL + AND d.entry_module_id <> COALESCE(g.entry_module_id, parent.entry_module_id, dt.entry_module_id) +ORDER BY d.id DESC +LIMIT 100; + +-- ========================================================= +-- 9. 重复二级分组检查:结果应为空 +-- ========================================================= +SELECT + pid, + document_type_id, + COUNT(*) AS duplicated_count, + STRING_AGG(id::text || ':' || name, ' / ' ORDER BY id) AS groups +FROM leaudit_evaluation_point_groups +WHERE deleted_at IS NULL + AND COALESCE(pid, 0) <> 0 + AND document_type_id IS NOT NULL +GROUP BY pid, document_type_id +HAVING COUNT(*) > 1 +ORDER BY duplicated_count DESC, pid, document_type_id; + +-- ========================================================= +-- 10. 一级分组缺入口模块检查:兼容期允许存在,但新链路应逐步清零 +-- ========================================================= +SELECT + id, + code, + name, + document_type_id, + sort_order, + is_enabled +FROM leaudit_evaluation_point_groups +WHERE deleted_at IS NULL + AND COALESCE(pid, 0) = 0 + AND entry_module_id IS NULL +ORDER BY sort_order, id; diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 0000000..5fca3f8 --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "failed", + "failedTests": [] +} \ No newline at end of file diff --git a/test-results/leaudit-playwright-entry-module-remaining-acceptance.js b/test-results/leaudit-playwright-entry-module-remaining-acceptance.js new file mode 100644 index 0000000..7f5f92a --- /dev/null +++ b/test-results/leaudit-playwright-entry-module-remaining-acceptance.js @@ -0,0 +1,167 @@ +const { chromium, request } = require('/home/wren-dev/Porject/leaudit-platform/legal-platform-frontend/node_modules/playwright'); + +const FRONTEND = process.env.LEAUDIT_FRONTEND_URL || 'http://172.16.0.59:5173'; +const BACKEND = process.env.LEAUDIT_BACKEND_URL || 'http://127.0.0.1:8096'; +const runId = `pwr${Date.now()}`; +const results = []; + +function record(name, ok, details = {}) { + results.push({ name, ok, details }); + console.log(`[${ok ? 'PASS' : 'FAIL'}] ${name}: ${JSON.stringify(details)}`); + if (!ok) throw new Error(`${name}: ${JSON.stringify(details)}`); +} + +async function asJson(response) { + try { + return await response.json(); + } catch { + return { text: await response.text() }; + } +} + +function unwrap(payload) { + if (payload && typeof payload === 'object' && Object.prototype.hasOwnProperty.call(payload, 'data')) { + return payload.data; + } + return payload; +} + +async function apiFetch(api, method, path, token, options = {}) { + const headers = { ...(options.headers || {}) }; + if (token) headers.Authorization = `Bearer ${token}`; + const response = await api.fetch(`${BACKEND}${path}`, { method, ...options, headers }); + return { response, body: await asJson(response) }; +} + +async function loginFrontendContext(browser) { + const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } }); + const loginResponse = await context.request.post(`${FRONTEND}/api/auth/password-login`, { + data: { username: '000', password: 'admin06111' }, + }); + const loginBody = await asJson(loginResponse); + if (!loginResponse.ok() || !loginBody?.access_token) { + throw new Error(`前端登录失败 ${loginResponse.status()} ${JSON.stringify(loginBody)}`); + } + return { context, token: loginBody.access_token }; +} + +async function createEntryModule(api, token) { + const payload = { + name: `PW验收政务入口-${runId}`, + description: 'playwright remaining acceptance', + path: '/govdoc/audits', + route_path: '/govdoc/audits', + menu_profile: 'govdoc', + features: ['home', 'govdoc_audits', 'govdoc_upload', 'rule_groups'], + tenants: [{ tenant_code: 'PUBLIC', tenant_name: '公共资源域', enabled: true, sort_order: 1 }], + }; + const { response, body } = await apiFetch(api, 'POST', '/api/v3/entry-modules', token, { data: payload }); + record('创建名字不含公文的 govdoc 入口成功', response.status() === 200, { status: response.status(), body }); + const module = unwrap(body); + record('govdoc 入口保存 menu_profile/features', module.menu_profile === 'govdoc' && module.features?.includes('govdoc_audits'), module); + return module; +} + +async function createDocType(api, token, moduleId) { + const payload = { + code: `pw.remaining.${runId}`, + name: `PW验收文档类型-${runId}`, + description: 'playwright remaining acceptance', + entryModuleId: Number(moduleId), + isEnabled: true, + sortOrder: 1, + ruleSetIds: [], + }; + const { response, body } = await apiFetch(api, 'POST', '/api/document-types', token, { data: payload }); + record('为验收入口创建文档类型成功', response.status() === 200, { status: response.status(), body }); + return unwrap(body); +} + +async function sidebarTexts(page) { + return await page.locator('.sidebar a.sidebar-menu-item').evaluateAll((els) => ( + els.map((el) => (el.textContent || '').replace(/\s+/g, ' ').trim()).filter(Boolean) + )); +} + +async function createCommonUserToken(api, adminToken) { + const sub = `pw-no-image-${runId}`; + const login = await apiFetch(api, 'POST', '/api/auth/login', null, { + data: { + userInfo: { + sub, + username: sub, + nickname: `PW无图标权限-${runId}`, + email: `${sub}@playwright.local`, + phone_number: '13800000000', + ou_id: 'pw-no-image', + ou_name: 'Playwright验收组织', + is_leader: false, + }, + area: '公共资源域', + expiresIn: 3600, + }, + }); + record('创建无图标权限测试用户登录成功', login.response.status() === 200, { status: login.response.status(), body: login.body }); + const loginData = unwrap(login.body); + const userId = Number(loginData.user_info?.user_id); + + const roles = await apiFetch(api, 'GET', '/api/v3/rbac/roles?page=1&page_size=200', adminToken); + const roleItems = unwrap(roles.body)?.items || []; + const commonRole = roleItems.find((item) => item.role_key === 'common'); + record('找到 common 角色用于无权限验收', Boolean(commonRole?.id), { commonRole }); + + const assign = await apiFetch(api, 'POST', `/api/v3/rbac/users/${userId}/roles`, adminToken, { + data: { role_ids: [Number(commonRole.id)] }, + }); + record('无图标权限测试用户分配 common 角色成功', assign.response.status() === 200, { status: assign.response.status(), body: assign.body }); + return loginData.access_token; +} + +async function main() { + const browser = await chromium.launch({ headless: true }); + const { context, token } = await loginFrontendContext(browser); + const api = await request.newContext(); + const page = await context.newPage(); + + const module = await createEntryModule(api, token); + await createDocType(api, token, module.id); + + await page.goto(`${FRONTEND}/`, { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {}); + await page.getByRole('button', { name: module.name, exact: true }).click({ timeout: 15000 }); + await page.waitForURL((url) => url.pathname === '/govdoc/audits' && url.searchParams.get('entryModuleId') === String(module.id), { timeout: 15000 }); + await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {}); + await page.waitForTimeout(1200); + + const side = await sidebarTexts(page); + const headingText = await page.locator('.govdoc-audit-scope h2').first().textContent({ timeout: 10000 }); + const storage = await page.evaluate(() => JSON.parse(sessionStorage.getItem('selectedEntryModuleContext') || 'null')); + + record('公文入口标题使用当前入口模块名称', headingText === `${module.name}文档列表`, { headingText, expected: `${module.name}文档列表` }); + record('公文入口上下文保存为 govdoc', storage?.menuProfile === 'govdoc' && Number(storage?.id) === Number(module.id), storage); + record('govdoc 侧栏显示公文列表/公文上传/规则分组', ['公文列表', '公文上传', '规则分组'].every((text) => side.includes(text)), { side }); + record('govdoc 侧栏不显示普通文件上传/文档列表', !side.includes('文件上传') && !side.includes('文档列表'), { side }); + + const commonToken = await createCommonUserToken(api, token); + const image403 = await apiFetch(api, 'POST', `/api/v3/entry-modules/${module.id}/image`, commonToken, { + multipart: { + file: { + name: 'entry-module.png', + mimeType: 'image/png', + buffer: Buffer.from('89504e470d0a1a0a', 'hex'), + }, + }, + }); + record('无 entry_module:image:write 用户上传入口图标返回 403', image403.response.status() === 403, { status: image403.response.status(), body: image403.body }); + + await api.dispose(); + await context.close(); + await browser.close(); + console.log('\nSUMMARY ' + JSON.stringify({ runId, pass: results.filter((r) => r.ok).length, fail: results.filter((r) => !r.ok).length, results }, null, 2)); +} + +main().catch((err) => { + console.error('\nERROR', err); + console.log('\nSUMMARY ' + JSON.stringify({ runId, pass: results.filter((r) => r.ok).length, fail: results.filter((r) => !r.ok).length, results }, null, 2)); + process.exit(1); +}); diff --git a/tests/test_cross_review_progress_permission.py b/tests/test_cross_review_progress_permission.py new file mode 100644 index 0000000..a2b0962 --- /dev/null +++ b/tests/test_cross_review_progress_permission.py @@ -0,0 +1,55 @@ +from fastapi_modules.fastapi_leaudit.services.impl.crossReviewServiceImpl import CrossReviewServiceImpl + + +def test_cross_review_task_item_masks_progress_without_permission(): + item = CrossReviewServiceImpl._build_task_item_vo( + row={ + "task_id": 10, + "task_name": "交叉评查任务", + "task_type": "CITY", + "doc_type_id": 2, + "doc_type_code": "contract", + "status": "in_progress", + "total_documents": 4, + "completed_documents": 1, + "current_user_role": "principal", + "current_user_can_confirm": True, + "create_time": None, + "evaluation_tenants": [], + "evaluation_regions": [], + }, + CanViewProgress=False, + ) + + assert item.progress is None + assert item.totalDocuments is None + assert item.completedDocuments is None + assert item.currentUserRole == "principal" + assert item.currentUserCanConfirm is True + + +def test_cross_review_task_item_keeps_progress_with_permission(): + item = CrossReviewServiceImpl._build_task_item_vo( + row={ + "task_id": 10, + "task_name": "交叉评查任务", + "task_type": "CITY", + "doc_type_id": 2, + "doc_type_code": "contract", + "status": "in_progress", + "total_documents": 4, + "completed_documents": 1, + "current_user_role": "participant", + "current_user_can_confirm": False, + "create_time": None, + "evaluation_tenants": [], + "evaluation_regions": [], + }, + CanViewProgress=True, + ) + + assert item.progress == 25 + assert item.totalDocuments == 4 + assert item.completedDocuments == 1 + assert item.currentUserRole == "participant" + assert item.currentUserCanConfirm is False diff --git a/tests/test_govdoc_permissions.py b/tests/test_govdoc_permissions.py new file mode 100644 index 0000000..2d4200d --- /dev/null +++ b/tests/test_govdoc_permissions.py @@ -0,0 +1,128 @@ +"""内部公文权限控制测试。""" + +import pytest +from starlette.responses import JSONResponse + +from fastapi_modules.fastapi_leaudit.controllers.govdocController import GovdocController + + +class _DenyPermissionService: + """拒绝所有权限的测试权限服务。""" + + async def CheckPermission(self, user_id: int, permission_key: str) -> bool: + """检查权限。""" + return False + + +class _AllowPermissionService: + """允许所有权限的测试权限服务。""" + + async def CheckPermission(self, user_id: int, permission_key: str) -> bool: + """检查权限。""" + return True + + +class _FakeGovdocService: + """记录调用的测试公文服务。""" + + def __init__(self) -> None: + self.list_called = False + self.upload_called = False + + async def ListDocuments(self, **kwargs): + """记录列表调用。""" + self.list_called = True + return {"items": [], "total": 0, "page": kwargs["page"], "pageSize": kwargs["pageSize"]} + + async def UploadDocument(self, **kwargs): + """记录上传调用。""" + self.upload_called = True + return {"documentId": 1} + + +def _find_endpoint(controller: GovdocController, path: str, method: str): + """根据路径和方法查找路由 endpoint。""" + full_path = f"{controller.router.prefix}{path}" + for route in controller.router.routes: + if getattr(route, "path", "") == full_path and method in getattr(route, "methods", set()): + return route.endpoint + raise AssertionError(f"未找到路由 {method} {full_path}") + + +@pytest.mark.asyncio +async def test_govdoc_list_requires_document_read_permission(): + """公文列表无查看权限时返回 403,且不调用业务服务。""" + controller = GovdocController() + service = _FakeGovdocService() + controller.GovdocService = service + controller.PermissionService = _DenyPermissionService() + endpoint = _find_endpoint(controller, "/documents", "GET") + + response = await endpoint( + page=1, + pageSize=20, + keyword=None, + fileExt=None, + region=None, + tenant_code=None, + entry_module_id=None, + type_ids=None, + document_type_id=None, + status=None, + resultStatus=None, + createdBy=None, + dateFrom=None, + dateTo=None, + payload={"user_id": 7}, + ) + + assert isinstance(response, JSONResponse) + assert response.status_code == 403 + assert service.list_called is False + + +@pytest.mark.asyncio +async def test_govdoc_upload_requires_document_create_permission(): + """公文上传无创建权限时返回 403,且不调用业务服务。""" + controller = GovdocController() + service = _FakeGovdocService() + controller.GovdocService = service + controller.PermissionService = _DenyPermissionService() + endpoint = _find_endpoint(controller, "/documents", "POST") + + response = await endpoint(file=object(), payload={"user_id": 7}) + + assert isinstance(response, JSONResponse) + assert response.status_code == 403 + assert service.upload_called is False + + +@pytest.mark.asyncio +async def test_govdoc_list_calls_service_when_permission_granted(): + """公文列表有查看权限时正常调用业务服务。""" + controller = GovdocController() + service = _FakeGovdocService() + controller.GovdocService = service + controller.PermissionService = _AllowPermissionService() + endpoint = _find_endpoint(controller, "/documents", "GET") + + response = await endpoint( + page=1, + pageSize=20, + keyword=None, + fileExt=None, + region=None, + tenant_code=None, + entry_module_id=None, + type_ids=None, + document_type_id=None, + status=None, + resultStatus=None, + createdBy=None, + dateFrom=None, + dateTo=None, + payload={"user_id": 7}, + ) + + assert response.data["total"] == 0 + assert service.list_called is True diff --git a/tests/test_home_dashboard_statistics.py b/tests/test_home_dashboard_statistics.py new file mode 100644 index 0000000..1aaece5 --- /dev/null +++ b/tests/test_home_dashboard_statistics.py @@ -0,0 +1,73 @@ +"""首页统计接口测试。""" + +import pytest + +from fastapi_modules.fastapi_leaudit.services.impl.homeServiceImpl import HomeServiceImpl + + +class _FakeDocument: + def __init__(self, *, audit_status: int, failed_count: int = 0, updated_at: str = "2026-05-23T10:00:00") -> None: + self.auditStatus = audit_status + self.failedCount = failed_count + self.updatedAt = updated_at + + +class _FakePage: + def __init__(self, *, documents, total_pages: int) -> None: + self.documents = documents + self.totalPages = total_pages + + +class _FakeDocumentService: + def __init__(self) -> None: + self.calls = [] + + async def ListDocuments(self, **kwargs): + self.calls.append(kwargs) + page = kwargs["Page"] + if page == 1: + return _FakePage( + documents=[ + _FakeDocument(audit_status=0, updated_at="2026-05-23T09:00:00"), + _FakeDocument(audit_status=2, updated_at="2026-05-23T09:30:00"), + _FakeDocument(audit_status=1, failed_count=0, updated_at="2026-05-03T10:00:00"), + _FakeDocument(audit_status=1, failed_count=2, updated_at="2026-05-20T10:00:00"), + ], + total_pages=2, + ) + if page == 2: + return _FakePage( + documents=[ + _FakeDocument(audit_status=1, failed_count=1, updated_at="2026-05-22T10:00:00"), + _FakeDocument(audit_status=1, failed_count=0, updated_at="2026-04-18T10:00:00"), + _FakeDocument(audit_status=0, updated_at="2026-05-10T10:00:00"), + ], + total_pages=2, + ) + return _FakePage(documents=[], total_pages=2) + + +@pytest.mark.asyncio +async def test_home_dashboard_statistics_uses_entry_scope_and_all_pages(): + """首页统计按入口模块与文档类型过滤,并拉取全量分页后计算。""" + document_service = _FakeDocumentService() + service = HomeServiceImpl(DocumentService=document_service) + + result = await service.GetDashboardStatistics( + UserId=7, + Today="2026-05-23", + TypeIds=[10, 11], + EntryModuleId=3, + ) + + assert result.todayPendingFiles == 2 + assert result.monthlyReviewedFiles == 3 + assert result.monthlyPassRate == 33 + assert result.issuesDetected == 3 + assert result.monthlyReviewGrowth.value == 200 + assert result.monthlyReviewGrowth.isUp is True + assert {call["EntryModuleId"] for call in document_service.calls} == {3} + assert {tuple(call["TypeIds"]) for call in document_service.calls} == {(10, 11)} + assert [call["Page"] for call in document_service.calls] == [1, 2] + assert all("DateFrom" not in call for call in document_service.calls) + assert all("DateTo" not in call for call in document_service.calls) diff --git a/tests/test_qichacha_config_client.py b/tests/test_qichacha_config_client.py new file mode 100644 index 0000000..b06d497 --- /dev/null +++ b/tests/test_qichacha_config_client.py @@ -0,0 +1,66 @@ +"""企查查配置与客户端测试。""" + +from __future__ import annotations + +import hashlib + +import pytest + +from fastapi_admin import config + + +def test_qichacha_settings_are_exported_from_app_toml(): + """企查查配置应通过 fastapi_admin.config 导出。""" + assert config.QICHACHA_BASE_URL == "https://api.qichacha.com" + assert config.QICHACHA_ENTERPRISE_PATH == "/ECIV4/GetBasicDetailsByName" + assert config.QICHACHA_DISHONESTY_PATH == "/ShixinCheck/GetList" + assert config.QICHACHA_TIMEOUT == 30 + assert config.QICHACHA_CACHE_DAYS == 30 + + +def test_qichacha_client_builds_expected_signature_headers(monkeypatch): + """企查查客户端应按 AppKey + Timespan + SecretKey 生成大写 MD5 Token。""" + from fastapi_modules.fastapi_leaudit.services.impl.qichachaClient import QichachaClient + + monkeypatch.setattr("time.time", lambda: 1779433125) + client = QichachaClient(AppKey="app-key", SecretKey="secret-key") + + headers = client.BuildHeaders() + + expected = hashlib.md5("app-key1779433125secret-key".encode("utf-8")).hexdigest().upper() + assert headers == {"Token": expected, "Timespan": "1779433125"} + + +@pytest.mark.asyncio +async def test_qichacha_client_parses_enterprise_and_dishonesty(monkeypatch): + """企查查客户端应分别解析工商与失信接口结果。""" + from fastapi_modules.fastapi_leaudit.services.impl.qichachaClient import QichachaClient + + calls: list[tuple[str, dict[str, str]]] = [] + + async def fake_request(self, Url: str, Params: dict[str, str]) -> dict: + calls.append((Url, Params)) + if "GetBasicDetailsByName" in Url: + return { + "Status": "200", + "Message": "成功", + "Result": {"Name": "广州测试有限公司", "CreditCode": "91440000TEST"}, + } + return { + "Status": "200", + "Message": "成功", + "Result": {"VerifyResult": 1, "Data": [{"Anno": "案号1"}]}, + } + + monkeypatch.setattr(QichachaClient, "Request", fake_request) + client = QichachaClient(AppKey="app-key", SecretKey="secret-key") + + enterprise = await client.GetEnterpriseInfo("广州测试有限公司") + dishonesty = await client.GetDishonestyInfo("广州测试有限公司") + + assert enterprise["Name"] == "广州测试有限公司" + assert enterprise["CreditCode"] == "91440000TEST" + assert dishonesty["VerifyResult"] == 1 + assert dishonesty["Data"][0]["Anno"] == "案号1" + assert calls[0][1] == {"key": "app-key", "keyword": "广州测试有限公司"} + assert calls[1][1] == {"key": "app-key", "searchKey": "广州测试有限公司"} diff --git a/tests/test_qichacha_service.py b/tests/test_qichacha_service.py new file mode 100644 index 0000000..19a134d --- /dev/null +++ b/tests/test_qichacha_service.py @@ -0,0 +1,194 @@ +"""企查查服务测试。""" + +from __future__ import annotations + +from datetime import UTC, datetime, timedelta +from types import SimpleNamespace + +import pytest + + +class _FakeSession: + async def commit(self): + return None + + async def refresh(self, obj): + return obj + + async def flush(self): + return None + + +class _FakeSessionContext: + async def __aenter__(self): + return _FakeSession() + + async def __aexit__(self, exc_type, exc, tb): + return None + + +async def _unexpected_upsert(cls, session, **fields): + pytest.fail("fresh cache should not upsert") + + +class _FakeClient: + def __init__(self): + self.calls: list[tuple[str, str]] = [] + + async def QueryCompany(self, Keyword: str): + self.calls.append(("company", Keyword)) + return ( + {"Name": "广州测试有限公司", "CreditCode": "91440000TEST"}, + {"VerifyResult": 1, "Data": [{"Anno": "案号1"}, {"Anno": "案号2"}]}, + "91440000TEST", + "广州测试有限公司", + ) + + async def GetEnterpriseInfo(self, Keyword: str): + self.calls.append(("enterprise", Keyword)) + return {"Name": "广州测试有限公司", "CreditCode": "91440000TEST"} + + async def GetDishonestyInfo(self, Keyword: str): + self.calls.append(("dishonesty", Keyword)) + return {"VerifyResult": 0, "Data": []} + + +@pytest.mark.asyncio +async def test_query_company_uses_fresh_cache(monkeypatch): + """未过期缓存应直接返回,不调用企查查 API。""" + from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo + from fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl import QichachaServiceImpl + + now = datetime.now(UTC) + record = SimpleNamespace( + Id=1, + searchKey="广州测试有限公司", + creditCode="91440000TEST", + companyName="广州测试有限公司", + enterprise={"Name": "广州测试有限公司", "CreditCode": "91440000TEST"}, + dishonesty={"VerifyResult": 0, "Data": []}, + created_at=now, + updated_at=now, + ) + fake_client = _FakeClient() + + async def fake_find(cls, session, Keyword): + return record + + monkeypatch.setattr( + "fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl.GetAsyncSession", + lambda: _FakeSessionContext(), + ) + monkeypatch.setattr(QichachaCompanyInfo, "FindByKeyword", classmethod(fake_find)) + monkeypatch.setattr(QichachaCompanyInfo, "Upsert", classmethod(_unexpected_upsert)) + + service = QichachaServiceImpl(Client=fake_client, CacheDays=30) + result = await service.QueryCompany(Keyword="广州测试有限公司", ForceRefresh=False) + + assert result.success is True + assert result.data is not None + assert result.data.companyName == "广州测试有限公司" + assert result.data.hasDishonesty is False + assert result.data.dishonestyCount == 0 + assert fake_client.calls == [] + + +@pytest.mark.asyncio +async def test_query_company_refreshes_when_forced(monkeypatch): + """强制刷新时应调用企查查 API 并写入缓存。""" + from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo + from fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl import QichachaServiceImpl + + old_record = SimpleNamespace( + Id=1, + searchKey="旧名称", + creditCode=None, + companyName=None, + enterprise=None, + dishonesty=None, + created_at=datetime.now(UTC) - timedelta(days=1), + updated_at=datetime.now(UTC) - timedelta(days=1), + ) + saved: dict[str, object] = {} + fake_client = _FakeClient() + + async def fake_find(cls, session, Keyword): + return old_record + + async def fake_upsert(cls, session, **fields): + saved.update(fields) + return SimpleNamespace( + Id=1, + searchKey=fields["SearchKey"], + creditCode=fields["CreditCode"], + companyName=fields["CompanyName"], + enterprise=fields["Enterprise"], + dishonesty=fields["Dishonesty"], + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC), + ) + + monkeypatch.setattr( + "fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl.GetAsyncSession", + lambda: _FakeSessionContext(), + ) + monkeypatch.setattr(QichachaCompanyInfo, "FindByKeyword", classmethod(fake_find)) + monkeypatch.setattr(QichachaCompanyInfo, "Upsert", classmethod(fake_upsert)) + + service = QichachaServiceImpl(Client=fake_client, CacheDays=30) + result = await service.QueryCompany(Keyword="广州测试有限公司", ForceRefresh=True) + + assert fake_client.calls == [("company", "广州测试有限公司")] + assert saved["SearchKey"] == "广州测试有限公司" + assert saved["CreditCode"] == "91440000TEST" + assert result.data is not None + assert result.data.hasDishonesty is True + assert result.data.dishonestyCount == 2 + + +@pytest.mark.asyncio +async def test_query_company_refreshes_stale_cache(monkeypatch): + """超过缓存天数的数据应自动刷新。""" + from fastapi_modules.fastapi_leaudit.models.qichachaCompanyInfo import QichachaCompanyInfo + from fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl import QichachaServiceImpl + + stale_record = SimpleNamespace( + Id=1, + searchKey="广州测试有限公司", + creditCode="OLD", + companyName="旧公司", + enterprise={"Name": "旧公司"}, + dishonesty={"VerifyResult": 0, "Data": []}, + created_at=datetime.now(UTC) - timedelta(days=90), + updated_at=datetime.now(UTC) - timedelta(days=90), + ) + fake_client = _FakeClient() + + async def fake_find(cls, session, Keyword): + return stale_record + + async def fake_upsert(cls, session, **fields): + return SimpleNamespace( + Id=1, + searchKey=fields["SearchKey"], + creditCode=fields["CreditCode"], + companyName=fields["CompanyName"], + enterprise=fields["Enterprise"], + dishonesty=fields["Dishonesty"], + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC), + ) + + monkeypatch.setattr( + "fastapi_modules.fastapi_leaudit.services.impl.qichachaServiceImpl.GetAsyncSession", + lambda: _FakeSessionContext(), + ) + monkeypatch.setattr(QichachaCompanyInfo, "FindByKeyword", classmethod(fake_find)) + monkeypatch.setattr(QichachaCompanyInfo, "Upsert", classmethod(fake_upsert)) + + service = QichachaServiceImpl(Client=fake_client, CacheDays=30) + result = await service.QueryCompany(Keyword="广州测试有限公司") + + assert fake_client.calls == [("company", "广州测试有限公司")] + assert result.data is not None + assert result.data.companyName == "广州测试有限公司" diff --git a/tests/test_review_document_payload_page_quality.py b/tests/test_review_document_payload_page_quality.py new file mode 100644 index 0000000..5ddcee3 --- /dev/null +++ b/tests/test_review_document_payload_page_quality.py @@ -0,0 +1,96 @@ +from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import DocumentDetailVO +from fastapi_modules.fastapi_leaudit.domian.vo.pageQualityVo import PageQualitySummaryVO +from fastapi_modules.fastapi_leaudit.services.impl.documentServiceImpl import DocumentServiceImpl + + +def test_review_document_payload_includes_page_quality_summary(): + detail = DocumentDetailVO( + documentId=71, + internalDocumentNo=10071, + versionGroupKey="vg-71", + versionNo=1, + rootVersionId=71, + previousVersionId=None, + typeId=10, + typeCode="case", + typeName="行政许可", + groupId=None, + groupName=None, + region="梅州", + tenantCode="MEIZHOU", + tenantName="梅州", + normalizedName="图片模糊测试", + fileId=7001, + fileName="(图片模糊)第71号.pdf", + fileExt="pdf", + mimeType="application/pdf", + fileSize=1024, + ossUrl="/bucket/documents/71.pdf", + processingStatus="completed", + currentRunId=9001, + runStatus="completed", + resultStatus="warning", + latestErrorCode=None, + latestErrorMessage=None, + totalScore=88, + passedCount=2, + failedCount=1, + skippedCount=0, + documentNumber="71", + auditStatus=0, + isTestDocument=False, + pageQualityRunId=501, + pageQualityRunStatus="completed", + pageQualitySummaryStatus="review", + pageQualityIssueCount=2, + pageQualityWarningText="发现疑似模糊页", + updatedAt="2026-05-23T10:00:00", + hasHistory=False, + totalVersions=1, + historyVersions=[], + remark=None, + pageCount=10, + pageQualitySummary=PageQualitySummaryVO( + runId=501, + runStatus="completed", + summaryStatus="review", + totalPages=10, + reviewPageCount=2, + rejectPageCount=0, + warningText="发现疑似模糊页", + pages=[3, 7], + finishedAt="2026-05-23T10:01:00", + ), + attachments=[], + ) + + payload = DocumentServiceImpl._buildReviewPageQualityPayload( + detail, + [ + {"pageNum": 7, "qualityStatus": "review", "qualityScore": 0.64, "reasonText": "图片略模糊"}, + {"pageNum": 3, "qualityStatus": "reject", "qualityScore": 0.25, "reasonText": "图片严重模糊"}, + ], + ) + + assert payload == { + "pageQualityRunId": 501, + "pageQualityRunStatus": "completed", + "pageQualitySummaryStatus": "review", + "pageQualityIssueCount": 2, + "pageQualityWarningText": "发现疑似模糊页", + "pageQualitySummary": { + "runId": 501, + "runStatus": "completed", + "summaryStatus": "review", + "totalPages": 10, + "reviewPageCount": 2, + "rejectPageCount": 0, + "warningText": "发现疑似模糊页", + "pages": [3, 7], + "finishedAt": "2026-05-23T10:01:00", + }, + "pageQualityResults": [ + {"pageNum": 3, "qualityStatus": "reject", "qualityScore": 0.25, "reasonText": "图片严重模糊"}, + {"pageNum": 7, "qualityStatus": "review", "qualityScore": 0.64, "reasonText": "图片略模糊"}, + ], + } diff --git a/tests/test_rule_write_scope.py b/tests/test_rule_write_scope.py index df821bb..419926c 100644 --- a/tests/test_rule_write_scope.py +++ b/tests/test_rule_write_scope.py @@ -1,5 +1,6 @@ from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException +import pytest from fastapi_modules.fastapi_leaudit.services.impl.rbacAdminServiceImpl import RbacAdminServiceImpl from fastapi_modules.fastapi_leaudit.services.impl.rbacServiceImpl import RbacServiceImpl @@ -225,3 +226,25 @@ def test_permission_cache_is_shared_and_can_invalidate_user(): PermissionServiceImpl.InvalidateUser(12345) assert 12345 not in first._permission_cache assert 12345 not in second._permission_cache + + +@pytest.mark.asyncio +async def test_rbac_admin_permission_assertion_uses_permission_service(monkeypatch): + service = RbacAdminServiceImpl() + checked_permissions: list[tuple[int, str]] = [] + + async def fake_context(user_id: int): + return {"can_manage": True, "is_super_admin": False} + + async def fake_check_permission(self, user_id: int, permission_key: str): + checked_permissions.append((user_id, permission_key)) + return permission_key != "rbac:roles:update" + + monkeypatch.setattr(service, "_getCurrentUserContext", fake_context) + monkeypatch.setattr(PermissionServiceImpl, "CheckPermission", fake_check_permission) + + with pytest.raises(LeauditException) as exc_info: + await service._assertPermissions(99, ["rbac:roles:update"]) + + assert exc_info.value.status == StatusCodeEnum.HTTP_403_FORBIDDEN + assert checked_permissions == [(99, "rbac:roles:update")] diff --git a/tests/test_usage_stats_role_permission_scope.py b/tests/test_usage_stats_role_permission_scope.py new file mode 100644 index 0000000..6f0bb79 --- /dev/null +++ b/tests/test_usage_stats_role_permission_scope.py @@ -0,0 +1,17 @@ +"""系统使用统计角色权限语义测试。""" + +from fastapi_modules.fastapi_leaudit.services.impl.usageStatsServiceImpl import UsageStatsServiceImpl + + +def test_usage_stats_service_does_not_require_admin_role_after_controller_permission_check(): + """统计服务不再用管理员角色二次拦截,权限由控制器权限点决定。""" + service = UsageStatsServiceImpl() + + service._assert_stats_access( + { + "is_global": False, + "can_manage": False, + "tenant_scope_value": "梅州", + "tenant_code": "MZ", + } + )