审批引擎设计文档

**版本**: v1.0
**最后更新**: 2026-06-04
**状态**: 设计草案

---

1. 概述

审批引擎(Approval Engine)是 TopCentral Mall 系统的核心业务组件,负责处理各类审批流程的创建、流转、审批、通知和归档。本文档描述审批引擎的整体架构设计、多级审批流程、自动升级机制以及与 WeChat Work 的集成方案。

---

2. 架构设计

┌─────────────────────────────────────────────────────────┐
│                    Approval Engine                       │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌────────┐  │
│  │ 创建服务  │  │ 流转引擎  │  │ 审批执行  │  │ 归档器 │  │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └───┬────┘  │
│       │             │             │             │       │
│  ┌────┴─────────────┴─────────────┴─────────────┴────┐  │
│  │               Approval DB (PostgreSQL)              │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
         │                 │                  │
         ▼                 ▼                  ▼
  ┌──────────┐    ┌──────────────┐    ┌──────────────┐
  │  Notifier │    │  Escalator   │    │  Audit Trail │
  └──────────┘    └──────────────┘    └──────────────┘

2.1 核心模块

模块职责关键组件
**Approval Creator**创建审批单、验证数据完整性`ApprovalService.create_approval()`
**Workflow Engine**按预设节点流转、条件分支`WorkflowEngine.advance()`
**Approval Executor**执行审批动作(通过/拒绝/驳回)`ApprovalExecutor.execute()`
**Escalator**超时自动升级`EscalationService.check_and_escalate()`
**Notifier**多渠道通知`WeChatWorkNotifier`, `EmailNotifier`
**Auditor**审计日志记录`AuditLogger.log()`

---

3. 多级审批流程(金额驱动)

3.1 审批层级定义

审批层级根据 **申请金额** 自动路由到不同的审批链:

金额范围审批链说明
¥0 – ¥10,000**销售经理**单级审批,销售经理直接审批
¥10,000 – ¥100,000销售 → **经理** → 结束二级审批
¥100,000 – ¥500,000销售 → 经理 → **总监**三级审批
¥500,000 以上销售 → 经理 → 总监 → **CEO**四级审批(含法务会签)

3.2 审批链(Approval Chain)

销售 (提交)
  │
  ▼
┌─────────────────────────────────────────┐
│  销售经理 (Level 1)                     │
│  - 金额权限: ¥0 - ¥100,000              │
│  - 处理超时: 24h → 自动升级到上级       │
└────────────┬────────────────────────────┘
             │
             ▼ (金额 > ¥10,000 时)
┌─────────────────────────────────────────┐
│  部门总监 / 销售总监 (Level 2)          │
│  - 金额权限: ¥100,000 - ¥500,000        │
│  - 处理超时: 24h → 自动升级到 CEO       │
└────────────┬────────────────────────────┘
             │
             ▼ (金额 > ¥100,000 时)
┌─────────────────────────────────────────┐
│  CEO / 总经理 (Level 3)                 │
│  - 金额权限: ¥500,000 以上              │
│  - 需法务会签 (超 ¥500,000)             │
└─────────────────────────────────────────┘

3.3 金额判定规则

def determine_approval_chain(amount: float) -> list:
    """根据金额确定审批链"""
    chain = [
        {"level": 1, "role": "sales_manager", "name": "销售经理"},
    ]
    if amount > 10000:
        chain.append({"level": 2, "role": "sales_director", "name": "销售总监"})
    if amount > 100000:
        chain.append({"level": 3, "role": "ceo", "name": "CEO / 总经理"})
    if amount > 500000:
        chain.append({"level": 4, "role": "legal", "name": "法务会签", "type": "countersign"})
    return chain

---

4. 自动升级机制(Auto-Escalation)

4.1 升级规则

条件触发动作通知对象
审批人 **24h 未处理**自动升级到上一级领导原审批人 + 上级领导
升级后 **24h 仍未处理**升级到再上一级(或 CEO)所有相关方
累计 **72h 未完结**紧急标注,通知所有管理员全管理层

4.2 升级流程

申请提交(等待审批)
     │
     ▼
┌──────────────────────┐
│  等待经理审批         │  ← 倒计时 24h
│  [⏰ 剩余 23:59:59]  │
└──────┬───────────────┘
       │ 超时
       ▼
┌──────────────────────┐
│  自动升级到总监       │  ← 原经理被跳过
│  发送通知给总监+经理  │
│  [⏰ 剩余 23:59:59]  │
└──────┬───────────────┘
       │ 再次超时
       ▼
┌──────────────────────┐
│  紧急状态 - 通知 CEO  │  ← 标记为 "urgent"
│  全管理层广播通知     │
└──────────────────────┘

4.3 定时任务实现

# cron_service.py
ESCLATION_CRON = {
    "name": "approval_escalation_check",
    "schedule": "*/30 * * * *",       # 每30分钟检查一次
    "description": "审批超时自动升级检查",
    "handler": "check_escalations",
}

async def check_escalations():
    """查询所有超时的待审批项,执行升级"""
    overdue = await ApprovalModel.find_overdue(hours=24)
    for item in overdue:
        if item.escalation_count == 0:
            # 首次超时: 升级到上级
            await escalate_to_supervisor(item)
        elif item.escalation_count == 1:
            # 二次超时: 升级到CEO
            await escalate_to_ceo(item)
        else:
            # 三次超时: 紧急标记
            await mark_as_urgent(item)
        item.escalation_count += 1
        item.escalated_at = datetime.utcnow()
        await item.save()

---

5. WeChat Work 通知集成

5.1 通知类型

通知类型触发时机目标用户消息模板
`new_approval`新审批单提交当前审批人审批通知卡片
`approval_passed`审批通过申请人通过通知
`approval_rejected`审批拒绝申请人 + 原因拒绝通知
`escalation_warning`升级前 2h 提醒当前审批人催办提醒
`escalation_notice`升级已触发上级 + 原审批人升级通知
`system_notice`系统异常管理员系统告警

5.2 消息卡片模板(Markdown)

{
  "touser": "user_id",
  "msgtype": "template_card",
  "template_card": {
    "card_type": "news_notice",
    "source": {
      "icon_url": "https://mall.topcentral.com/static/logo.png",
      "desc": "TopCentral Mall 审批系统"
    },
    "main_title": {
      "title": "📋 新的审批申请",
      "desc": "请及时处理"
    },
    "card_image": { "url": "" },
    "vertical_content_list": [
      {
        "title": "审批类型",
        "desc": "客户信用额度申请"
      },
      {
        "title": "申请人",
        "desc": "张三 (sales@topcentral.com)"
      },
      {
        "title": "金额",
        "desc": "¥ 150,000.00"
      },
      {
        "title": "申请时间",
        "desc": "2026-06-04 10:30:00"
      }
    ],
    "horizontal_content_list": [
      { "keyname": "当前步骤", "value": "销售经理审批" },
      { "keyname": "超时时间", "value": "2026-06-05 10:30 (剩余 23h)" }
    ],
    "card_action": {
      "type": 1,
      "url": "https://mall.topcentral.com/approval/detail?id=APP20260604001"
    },
    "jump_list": [
      { "type": 1, "title": "查看详情", "url": "https://mall.topcentral.com/approval/detail?id=APP20260604001" },
      { "type": 1, "title": "快速审批", "url": "https://mall.topcentral.com/approval/quick-approve?id=APP20260604001" }
    ]
  }
}

5.3 通知适配器接口

class WeChatWorkNotifier:
    """企业微信通知适配器"""
    
    def __init__(self):
        self.corp_id = os.getenv("WECHAT_CORP_ID")
        self.agent_id = os.getenv("WECHAT_AGENT_ID")
        self.secret = os.getenv("WECHAT_SECRET")
        self.token_cache = {}
    
    async def get_access_token(self) -> str:
        """获取 access_token(缓存 + 自动刷新)"""
        if self.token_cache.get("expires_at", 0) > time.time():
            return self.token_cache["token"]
        # 调用企业微信API获取新token
        ...
    
    async def send_approval_notification(self, approval: ApprovalModel, 
                                          notification_type: str):
        """发送审批通知"""
        template = self._build_template(approval, notification_type)
        await self._send_message(approval.approver_id, template)
    
    async def send_escalation_notice(self, approval: ApprovalModel):
        """发送升级通知给上级"""
        supervisor = await UserService.get_supervisor(approval.approver_id)
        template = self._build_escalation_template(approval)
        await self._send_message(supervisor.wechat_id, template)
        # 同时通知原审批人
        await self._send_message(
            approval.approver_id,
            self._build_escalation_warning_template(approval)
        )

---

6. 数据库设计

6.1 核心表结构

-- 审批单主表
CREATE TABLE approvals (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    approval_no     VARCHAR(32) UNIQUE NOT NULL,       -- 审批编号, e.g. APP20260604001
    type            VARCHAR(32) NOT NULL,                -- 审批类型
    title           VARCHAR(200) NOT NULL,               -- 审批标题
    applicant_id    UUID NOT NULL,                       -- 申请人
    department_id   UUID,                                -- 部门
    amount          DECIMAL(15,2) DEFAULT 0,             -- 金额
    status          VARCHAR(20) DEFAULT 'pending',       -- pending/approved/rejected/cancelled
    current_step    INT DEFAULT 1,                       -- 当前步骤
    total_steps     INT NOT NULL,                        -- 总步骤数
    escalation_count INT DEFAULT 0,                      -- 升级次数
    form_data       JSONB,                               -- 申请表单数据
    created_at      TIMESTAMP DEFAULT NOW(),
    updated_at      TIMESTAMP DEFAULT NOW(),
    completed_at    TIMESTAMP
);

-- 审批节点表
CREATE TABLE approval_nodes (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    approval_id     UUID NOT NULL REFERENCES approvals(id),
    step            INT NOT NULL,                        -- 步骤序号
    role            VARCHAR(32) NOT NULL,                -- 角色
    approver_id     UUID,                                -- 审批人
    status          VARCHAR(20) DEFAULT 'pending',       -- pending/approved/rejected/skipped
    comment         TEXT,                                -- 审批意见
    deadline        TIMESTAMP,                           -- 处理截止时间
    escalated       BOOLEAN DEFAULT FALSE,               -- 是否已升级
    processed_at    TIMESTAMP,
    created_at      TIMESTAMP DEFAULT NOW()
);

-- 审批操作日志
CREATE TABLE approval_logs (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    approval_id     UUID NOT NULL REFERENCES approvals(id),
    action          VARCHAR(32) NOT NULL,                -- submit/approve/reject/escalate/comment
    operator_id     UUID NOT NULL,                       -- 操作人
    operator_name   VARCHAR(100),
    detail          JSONB,                               -- 操作详情
    created_at      TIMESTAMP DEFAULT NOW()
);

-- 索引
CREATE INDEX idx_approvals_status ON approvals(status);
CREATE INDEX idx_approvals_applicant ON approvals(applicant_id);
CREATE INDEX idx_approvals_amount ON approvals(amount);
CREATE INDEX idx_approval_nodes_approver ON approval_nodes(approver_id);
CREATE INDEX idx_approval_nodes_deadline ON approval_nodes(deadline) WHERE status = 'pending';

---

7. API 设计

方法路径说明
POST`/api/v1/mall/approval/create`创建审批单
GET`/api/v1/mall/approval/{id}`获取审批详情
POST`/api/v1/mall/approval/{id}/approve`通过审批
POST`/api/v1/mall/approval/{id}/reject`拒绝审批
POST`/api/v1/mall/approval/{id}/recall`撤回申请
GET`/api/v1/mall/approval/my-pending`我的待审批列表
GET`/api/v1/mall/approval/my-history`我的历史审批
POST`/api/v1/mall/approval/{id}/escalate`手动升级
GET`/api/v1/mall/approval/stats`审批统计
POST`/api/v1/mall/approval/{id}/remind`催办提醒

---

8. 与现有系统的集成

8.1 与现有 `approval_service.py` 的关系

现有的 backend/app/services/approval_service.py 提供了:

  • 审批类型枚举、审批节点配置、AI 辅助审批配置
  • 基础角色定义(sales, sales_manager, sales_director, finance, hr, admin 等)
  • 新引擎将:

  • **复用** 现有枚举和节点配置
  • **增强** 金额驱动的动态审批链
  • **实现** 原有的 `AUTO_APPROVE_RULES` 作为前置条件引擎
  • **扩展** 升级机制和 WeChat Work 通知
  • 8.2 与 RBAC 系统的集成

    Approval Engine → RBAC Service → User Roles
         │                │
         ▼                ▼
    审批节点角色映射     用户权限校验

    ---

    9. 安全与审计

    维度策略
    权限校验每个审批操作均通过 RBAC 校验
    操作审计所有审批操作记录到 `approval_logs`
    数据加密敏感字段(金额、审批意见)使用 AES-256 加密
    防篡改关键审批状态变更需签名校验
    合规审批历史保留至少 3 年

    ---

    10. 实施路线图

    阶段内容预计工时
    Phase 1动态审批链 + 金额判定3 天
    Phase 2自动升级机制 + 定时任务2 天
    Phase 3WeChat Work 通知集成3 天
    Phase 4审计日志 + 报表2 天
    Phase 5测试 + 文档 + 部署2 天
    **合计****12 天**

    ---

    11. 附录

    11.1 关键决策记录

    决策选项选择原因
    审批链配置方式代码 vs 数据库**数据库**支持运行时动态调整
    通知渠道优先级WeChat > Email > SMS**WeChat 为主**企业内通讯标准
    升级检查频率15m / 30m / 1h**30 分钟**平衡实时性和性能
    超时阈值12h / 24h / 48h**24h**行业常见标准

    11.2 相关文件

  • [审批服务源码](/backend/app/services/approval_service.py)
  • [RBAC 服务](/backend/app/services/rbac_service.py)
  • [定时任务服务](/backend/app/services/cron_service.py)