计费与账单

1. 实时计费流程

每次通话结束时,Wholesale 自动:

通话结束
  │
  ▼
计算话费 (卖价)
  │
  ├── 写入 wholesale_cdrs 话单
  ├── 扣减租户余额 (SQL: balance = balance - price)
  ├── 报告熔断器 (成功/失败)
  ├── 记录滑动窗口事件 (ASR/ACD)
  └── 上报 Prometheus 指标

计费精度规则(0.5+):

  • 向上取整到秒:计费时长在计价前统一向上取整到整秒。
  • 账期日期校验:账期/账单日期设置在保存时校验——过去会造成静默错账的错误日期配置现在会被直接拒绝。
  • 允许负数金额:贷记与话后调整走与计费相同的账本,争议修正只是一条账目,不再需要外部表格。
  • CDR 携带命中路由 id:每条 wholesale CDR 都带有计费上下文中的路由 id,每通被计费的呼叫都能追溯到具体计价的费率条目。
  • 批量话单写入:呼叫记录钩子按批处理,高话务量下每秒数千条 CDR 不再逐行挤占呼叫路径。

1.1 CDR 字段

字段说明
call_idSIP Call-ID
tenant_id租户 ID
trunk_id使用的中继
caller / callee主叫/被叫
call_start / call_end起止时间
ring_duration振铃时长
talk_duration通话时长
billable_duration计费时长
sell_rate / sell_price卖费率/卖价
buy_rate / buy_price买费率/买价
profit利润
sip_codeSIP 最终状态码
answered是否应答

2. 话单查询

Wholesale → 话单管理:

Wholesale 账单与话单控制台

支持筛选条件:

  • 时间范围
  • 租户
  • 中继
  • 主叫/被叫
  • 应答/未应答
  • SIP 状态码

2.1 CDR 导出

方式说明
同步导出即时下载 CSV(小数据量)
异步导出后台任务,生成 gzip CSV(大数据量)

异步导出流程:

  1. 创建导出任务(wholesale_export_tasks 表)
  2. 后台 Worker 流式生成 gzip CSV
  3. 完成后在 导出任务 列表下载

2.2 话单重算(Rebill)

话单管理 → 重算:修改费率后对历史话单重新计费。

  • 按时间范围和租户筛选
  • 使用当前费率表重新计算
  • 更新 CDR 和租户余额

3. 账单周期

3.1 配置

租户详情 → 账单设置:

字段说明
周期类型Weekly / Monthly
结算日每月几号 / 每周几
自动归档是否自动归档已结算 CDR

3.2 账单生成

后台任务每小时检查:

  1. 查找到期的账单周期
  2. 汇总该周期内的 CDR
  3. 生成 wholesale_bills 记录:
    • 总金额、通话数、ASR、总时长
    • 账单状态:draft → confirmed → paid

3.3 账单操作

操作说明
查看账单明细(按中继/日期汇总)
打印生成 HTML 账单页面
下载导出 CSV
确认标记为已确认
删除删除草稿账单

4. 充值与余额管理

租户详情 → 充值:

  • 金额
  • 凭证图片(上传到服务器本地或 S3)
  • 系统记录到 rustpbx_recharge_logs

租户详情 → 生成账单:

  • 手动触发当期账单生成

5. 数据库要求

Wholesale 计费涉及大量并发写入,数据库要求:

项目MySQLPostgreSQL
事务隔离READ COMMITTEDREAD COMMITTED
连接池每节点 10-20 连接同左
索引migration 自动创建同左
CDR 分区建议按月分区(手动)建议按月分区(手动)

CDR 数据增长估算:

  • 每通电话 1 条 CDR ≈ 1KB
  • 10 万通/天 ≈ 100MB/天 ≈ 3GB/月
  • 建议对 wholesale_cdrs 表按月分区或定期归档