- 4张表: voucher_template, voucher_rule, voucher_instance, voucher_usage_log - 可配置规则引擎: registry + validators + engine - 8种内置规则: min_amount, max_amount, applicable_product_type, applicable_product, exclude_product, max_usage_count, valid_period, user_level - CRUD定义 + API接口 + 前端页面 - SQL建表脚本 + RBAC权限配置 - 一次性使用,不找零
234 lines
7.3 KiB
Markdown
234 lines
7.3 KiB
Markdown
# voucher — 代金券模块
|
||
|
||
独立代金券管理模块,支持**可配置规则引擎**,一次性使用,不找零。
|
||
|
||
## 核心架构
|
||
|
||
```
|
||
模板(类别) → 定义规则集
|
||
实例(代金券)→ 属于某个模板,继承规则
|
||
使用流水 → 记录每次消费抵扣
|
||
```
|
||
|
||
### 表结构
|
||
| 表 | 说明 |
|
||
|---|---|
|
||
| voucher_template | 代金券模板(面值、有效期、发行量、状态) |
|
||
| voucher_rule | 规则定义(模板关联,可增删启用禁用) |
|
||
| voucher_instance | 券实例(一次性使用,状态:unused/used/expired) |
|
||
| voucher_usage_log | 使用流水(订单、抵扣金额、产品信息) |
|
||
|
||
---
|
||
|
||
## 可配置规则引擎
|
||
|
||
规则通过 `@register_rule` 装饰器注册到 `RULE_REGISTRY`,新增规则只需写 validator 函数,无需修改引擎代码。
|
||
|
||
### 内置规则类型
|
||
|
||
| rule_type | 说明 | rule_config 示例 |
|
||
|-----------|------|------------------|
|
||
| `min_amount` | 最低消费门槛 | `{"min_value": 100}` |
|
||
| `max_amount` | 最高消费限制 | `{"max_value": 1000}` |
|
||
| `applicable_product_type` | 限定产品类型(llm/image/video/audio) | `{"product_types": ["llm", "image"]}` |
|
||
| `applicable_product` | 限定特定产品(具体模型名) | `{"products": ["gpt-4", "claude-3"]}` |
|
||
| `exclude_product` | 排除特定产品 | `{"products": ["gpt-4"]}` |
|
||
| `max_usage_count` | 最大使用次数 | `{"max_count": 1}` |
|
||
| `valid_period` | 有效期检查 | `{}` (由实例 valid_from/valid_to 处理) |
|
||
| `user_level` | 用户等级限制 | `{"min_level": 2}` |
|
||
|
||
### 规则执行流程
|
||
1. 查询券实例状态(unused + 未过期)
|
||
2. 加载模板关联的所有启用规则(按 sort_order 排序)
|
||
3. 依次执行 validator,任一失败即拒绝
|
||
4. 全部通过 → 计算抵扣金额 = min(面值, 消费金额)
|
||
5. 记录流水 + 标记券为已使用(一次性作废)
|
||
|
||
### 新增规则步骤
|
||
```python
|
||
# rules/validators.py
|
||
@register_rule('new_rule_type')
|
||
def check_new_rule(config, context):
|
||
# config: 从 rule_config JSON 解析
|
||
# context: 包含 request_amount, product_type, product_name, user_level 等
|
||
if not some_condition:
|
||
return False, "不满足条件"
|
||
return True, None
|
||
```
|
||
然后在模板管理界面添加 `rule_type: "new_rule_type"` 的规则记录即可。
|
||
|
||
---
|
||
|
||
## 与其他模块交互
|
||
|
||
### llmage 模块(消费时使用代金券)
|
||
|
||
```python
|
||
# llmage 的计费逻辑中调用 voucher 引擎
|
||
from voucher.rules.engine import apply_voucher, get_available_vouchers
|
||
|
||
# 查询客户可用代金券
|
||
vouchers = get_available_vouchers(sor, customer_id, context={
|
||
'product_type': 'llm', # 从 llm.catelog 获取
|
||
'product_name': 'gpt-4', # 具体模型名
|
||
'request_amount': amount,
|
||
'user_level': customer.level
|
||
})
|
||
|
||
# 使用代金券抵扣
|
||
ok, deducted, err = apply_voucher(sor, instance_id, customer_id, order_id, context={
|
||
'request_amount': amount,
|
||
'product_type': 'llm',
|
||
'product_name': 'gpt-4'
|
||
})
|
||
|
||
# 批量使用多张券
|
||
from voucher.rules.engine import batch_apply_vouchers
|
||
result = batch_apply_vouchers(sor, customer_id, order_id, voucher_ids, context)
|
||
# result: {total_deducted: 150.0, remaining: 50.0, details: [...]}
|
||
# remaining > 0 时从余额扣减
|
||
```
|
||
|
||
### accounting 模块(余额扣减联动)
|
||
|
||
```python
|
||
# accounting 消费流程中先尝试代金券,剩余从余额扣
|
||
total_amount = calculate_consumption(customer_id, period)
|
||
|
||
# Step 1: 尝试代金券抵扣
|
||
result = batch_apply_vouchers(sor, customer_id, order_id, voucher_ids, context)
|
||
|
||
# Step 2: 剩余金额从余额扣减
|
||
if result['remaining'] > 0:
|
||
accounting.deduct_balance(customer_id, result['remaining'], order_id)
|
||
|
||
# Step 3: 记录完整账单
|
||
accounting.record_order(order_id, total_amount,
|
||
voucher_deducted=result['total_deducted'],
|
||
balance_deducted=result['remaining'])
|
||
```
|
||
|
||
### dapi 模块(客户自助查询)
|
||
|
||
```python
|
||
# 客户通过 API 查询自己的可用代金券
|
||
# dapi 端点调用 voucher 引擎
|
||
available = get_available_vouchers(sor, customer_id)
|
||
```
|
||
|
||
### 集成点总结
|
||
|
||
| 调用方 | 场景 | 调用函数 |
|
||
|--------|------|----------|
|
||
| llmage | 推理/生成时抵扣 | `apply_voucher()` |
|
||
| accounting | 月度账单结算 | `batch_apply_vouchers()` |
|
||
| dapi | 客户查询可用券 | `get_available_vouchers()` |
|
||
| 任意模块 | 新增规则类型 | `@register_rule` + 模板管理界面 |
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
voucher/
|
||
├── voucher/ # Python 包
|
||
│ ├── __init__.py
|
||
│ └── init.py # 模块初始化 + ServerEnv 注册
|
||
├── rules/ # 规则引擎(纯 Python)
|
||
│ ├── registry.py # @register_rule 装饰器
|
||
│ ├── validators.py # 内置规则校验器
|
||
│ └── engine.py # 校验/使用/批量使用
|
||
├── wwwroot/ # 前端
|
||
│ ├── index.ui # 入口页(卡片导航)
|
||
│ ├── menu.json # 菜单定义
|
||
│ └── api/ # API 端点
|
||
│ ├── template/ # 模板 CRUD
|
||
│ ├── rule/ # 规则 CRUD
|
||
│ ├── instance/ # 实例 CRUD
|
||
│ ├── usage/ # 流水 CRUD
|
||
│ ├── apply_voucher.dspy # 使用代金券
|
||
│ ├── get_available.dspy # 查询可用券
|
||
│ └── rule_types.dspy # 获取规则类型列表
|
||
├── models/ # 表定义 JSON
|
||
├── json/ # CRUD 定义 JSON
|
||
├── sql/
|
||
│ └── tables.sql # 建表 + 编码初始化
|
||
├── scripts/
|
||
│ └── load_path.py # RBAC 权限注册
|
||
├── pyproject.toml
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## 部署步骤
|
||
|
||
### 1. 代码部署
|
||
```bash
|
||
cd ~/repos/voucher && git pull
|
||
cd ~/repos/sage/pkgs && ln -sf ~/repos/voucher voucher
|
||
cd voucher && ~/repos/sage/py3/bin/pip install -e .
|
||
```
|
||
|
||
### 2. 数据库建表
|
||
```bash
|
||
mysql -u root -p sage < ~/repos/voucher/sql/tables.sql
|
||
```
|
||
|
||
### 3. Sage 集成
|
||
```python
|
||
# sage/app/sage.py
|
||
from voucher.init import load_voucher
|
||
# ... in init():
|
||
load_voucher()
|
||
```
|
||
|
||
```bash
|
||
# sage/build.sh 安装循环
|
||
for m in ... voucher
|
||
```
|
||
|
||
### 4. 菜单入口
|
||
```json
|
||
// sage/wwwroot/global_menu.ui items 数组
|
||
,{
|
||
"name": "voucher",
|
||
"label": "代金券",
|
||
"icon": "fa fa-ticket",
|
||
"url": "{{entire_url('/voucher/index.ui')}}",
|
||
"target": "app.sage_main_content"
|
||
}
|
||
```
|
||
|
||
### 5. RBAC 权限
|
||
```bash
|
||
cd ~/repos/sage && ./py3/bin/python ~/repos/voucher/scripts/load_path.py
|
||
```
|
||
|
||
### 6. 重启
|
||
```bash
|
||
cd ~/repos/sage && ./stop.sh && ./start.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 使用示例
|
||
|
||
### 创建模板 + 配置规则
|
||
1. 模板管理 → 新增 → 名称"新用户满减券",面值 50,有效期 30 天
|
||
2. 点击模板 → 规则配置 → 添加规则:
|
||
- 规则类型: `min_amount`,配置: `{"min_value": 100}`
|
||
- 规则类型: `applicable_product_type`,配置: `{"product_types": ["llm"]}`
|
||
|
||
### 发放代金券
|
||
1. 券实例管理 → 新增 → 选择模板,填写客户 ID
|
||
2. 系统自动生成券码,设置有效期
|
||
|
||
### 消费时抵扣
|
||
```python
|
||
# llmage 推理完成后
|
||
context = {'request_amount': 120.0, 'product_type': 'llm', 'product_name': 'gpt-4'}
|
||
result = batch_apply_vouchers(sor, customer_id, order_id, [vid1, vid2], context)
|
||
# → 抵扣 50(满100可用),剩余 70 从余额扣
|
||
```
|