跳转至

业务流程图集

跨模块端到端流程,供测试设计用例与新人理解业务。每图附关键校验点。 功能全景见 产品需求总览;业务规则见 membership-agent-sales-guide.md;表结构见 data-model.md

1. 用户注册 → 购买会员 → 生图

sequenceDiagram
    participant U as 用户
    participant BE as backend
    participant DB as DB
    participant PAY as 支付渠道

    U->>BE: POST /api/auth/send-code
    BE->>U: 发短信
    U->>BE: POST /api/auth/login
    BE->>DB: 创建/查 users
    BE-->>U: User JWT
    U->>BE: GET /api/billing/plans
    U->>BE: POST /api/billing/orders
    BE->>DB: orders(pending)
    U->>BE: POST /api/billing/orders/{id}/prepay
    U->>PAY: 支付
    PAY->>BE: POST /api/payment/notify/{method}
    BE->>BE: mark_paid(验签+幂等)
    BE->>DB: subscriptions + usage_quotas(+积分) + transaction_ledger + commission_records(accrued)
    BE-->>PAY: OK
    U->>BE: 生图请求(扣点)
    BE->>DB: usage_quotas.used += credits + consumption_records
    BE-->>U: 生成结果(落 OSS 占容)

校验点

  • 支付回调幂等:同 transaction_id 重复 notify 不重复加配额
  • 配额不足生图 → 402
  • 生成图必须落 OSS 并占容(见流程 4)

2. 代理推广 → 客户绑定 → 分账 → 提现

sequenceDiagram
    participant A as 代理商
    participant C as 客户
    participant BE as backend
    participant DB as DB

    A->>BE: 登录(as_agent=true)
    BE->>DB: 创建 agents 行
    A->>BE: GET /api/agents/me(拿 agent_code)
    C->>BE: GET /api/landing/{referral_code}
    BE->>DB: agent_link_clicks+1
    C->>BE: POST /api/landing/{code}/bind(登录后)
    BE->>DB: customer_agent_bindings(唯一约束)
    C->>BE: 购买会员支付成功
    BE->>DB: commission_records(accrued) 按规则生成
    Note over BE,DB: accrued 不增加 balance_commission
    A->>BE: POST /api/admin/commission-settlements/close
    BE->>DB: accrued→settled + balance_commission += 汇总(幂等)
    A->>BE: POST /api/billing/agents/me/withdraw
    BE->>DB: withdrawals(pending) + balance_commission 预占
    Note over BE: Admin 审批
    BE->>DB: approve → withdrawn += ; reject → 回滚预占

校验点

  • 客户只能绑一个代理(customer_agent_bindings 唯一)
  • 未月结的 accrued 不可提现
  • 月结关账幂等:重复关账不双加
  • 提现 reject 回滚预占余额

3. L1/L2 二级代理分账

flowchart LR
    L1["一级代理<br/>sub_agent_share_rate=30"]
    L2["二级代理<br/>(parent=L1)"]
    Cust["二级代理的客户"]

    L1 -->|"promote-sub-agent"| L2
    Cust -->|"下单支付成功"| Calc["计提佣金池"]
    Calc -->|"二级规则一笔"| L2Pool["二级 accrued"]
    Calc -->|"L1 佣金池 × share_rate"| L2Extra["二级额外 accrued"]
    Calc -->|"L1 佣金池 × (1-share_rate)"| L1Pool["一级 accrued"]

校验点

  • sub_agent_share_rate 仅一级代理档案持有(0~50)
  • 二级客户成交产生:二级一笔 + 一级再一笔(池内按 share_rate 拆)
  • 提拔二级前客户须已绑定该一级

4. 存储占容全生命周期

flowchart TD
    Upload["用户上传 / 生成图落 OSS"]
    Check{"assert<br/>used + size ≤ total?"}
    UploadOK["上传成功"]
    Commit["used += size"]
    UploadFail["拒绝(存储空间不足)"]

    Delete["删除资产 / 软删任务"]
    Release["used -= size"]

    Upload --> Check
    Check -->|"是"| UploadOK --> Commit
    Check -->|"否"| UploadFail
    Delete --> Release

占容入口

场景 入口 字段
画布 presign 上传 /canvas/assets/confirm-upload object_key, size
画布代传 /canvas/upload 成功即 commit
工作区参考图 /user/storage/upload 成功即 commit
用户资产 /user-assets/upload 落库即 commit
AI 生成图 Worker / 同步生图 generation_storage_persist

释容入口

场景 入口
画布删资产 /canvas/assets/release-storage
用户资产软删 UserAssetService.delete_asset
Admin 软删任务 TaskService.soft_delete_task(按 image_sizes

校验点

  • 上传超限 → 400「存储空间不足」
  • used 不为负
  • 首次创建 storage 桶时 used 初始化为未软删 user_assets.size 合计
  • 订阅激活同步 total,不重置 used

5. 日终对账与单户回放

sequenceDiagram
    participant OP as 运营/Admin
    participant BE as backend
    participant DB as DB

    OP->>BE: POST /api/admin/billing/recon/run (run_date)
    BE->>DB: 扫描全体用户/代理账本
    BE->>DB: 写 recon_batches(差异列表)
    BE-->>OP: 批次结果(绿灯/红灯)
    alt 发现差异
        OP->>BE: POST /api/admin/billing/replay/user (phone)
        BE->>DB: 重算该户账本
        BE->>DB: 修复余额(以账本为准)
        BE-->>OP: 修复结果
    end

校验点

  • 对账恒等式:物化余额 ≈ Σ(ledger) ≈ Σ(业务表)
  • 单户回放以账本为真相源修复余额
  • biz_date(列表筛选)≠ run_date(对账执行日)

6. 画布项目乐观锁

sequenceDiagram
    participant U1 as 用户TabA
    participant U2 as 用户TabB
    participant BE as backend
    participant DB as DB

    U1->>BE: POST /api/canvas/projects(创建)
    BE->>DB: project(revision=0)
    U2->>BE: GET project(拿到 revision=0)
    U1->>BE: PUT project (expectedRevision=0)
    BE->>DB: revision=1
    BE-->>U1: 200 OK (revision=1)
    U2->>BE: PUT project (expectedRevision=0)
    BE-->>U2: 409 冲突
    U2->>BE: GET project(拿 revision=1 重试)

校验点

  • expectedRevision 不匹配 → HTTP 409
  • 项目按 user_id 隔离,UserA 不可读写 UserB 项目
  • 删文件夹 → 项目 folder_id 变 NULL,项目不删