5.1 KiB
Raw Blame History

name version description trigger_conditions
voucher-module 1.0.0 代金券模块:可配置规则引擎、一次性使用、模板-规则-实例三层架构
用户询问代金券功能
需要新增规则类型
代金券与 llmage/accounting 集成
代金券表结构或 API 变更
创建新的代金券模板或使用代金券

voucher 代金券模块

架构

模板 (voucher_template)
  └─ 规则集 (voucher_rule) ← 可配置,增删不影响代码
       └─ 实例 (voucher_instance) ← 继承模板规则,一次性使用
            └─ 流水 (voucher_usage_log)

核心原则

  • 一次性使用:代金券使用后直接作废,不找零、无余额
  • 规则可配置:新增规则类型只需写 validator 函数 + @register_rule 装饰器
  • 动态执行:使用时按模板 sort_order 顺序依次校验规则

表结构

用途
voucher_template 模板(面值、有效期、发行量、状态)
voucher_rule 规则模板ID、类型、JSON配置、启用/禁用、排序)
voucher_instance 实例(券码、状态 unused/used/expired、面值、有效期
voucher_usage_log 流水(订单、抵扣金额、产品、操作人)

内置规则类型

rule_type config 说明
min_amount {"min_value": 100} 最低消费
max_amount {"max_value": 1000} 最高消费
applicable_product_type {"product_types": ["llm","image"]} 限定产品类型
applicable_product {"products": ["gpt-4"]} 限定特定产品
exclude_product {"products": ["gpt-4"]} 排除特定产品
max_usage_count {"max_count": 1} 最大使用次数
valid_period {} 有效期(由实例字段处理)
user_level {"min_level": 2} 用户等级

新增规则类型

# rules/validators.py
@register_rule('new_rule_type')
def check_new_rule(config, context):
    # config: rule_config JSON 解析后的 dict
    # context: {request_amount, product_type, product_name, user_level, ...}
    if not some_condition:
        return False, "不满足条件"
    return True, None

然后在模板管理界面为模板添加规则记录即可生效,无需改引擎代码。

规则执行流程

  1. 查实例状态 (unused + 未过期)
  2. 加载模板启用规则 (sort_order 排序)
  3. 逐条执行 validator任一失败即拒绝
  4. 全部通过 → 抵扣 = min(面值, 消费金额)
  5. 写流水 + 标记券 used

与其他模块交互

llmage (推理时使用券)

from voucher.rules.engine import apply_voucher, batch_apply_vouchers, get_available_vouchers

# 查询可用
vouchers = get_available_vouchers(sor, customer_id, context={
    'product_type': 'llm', 'product_name': 'gpt-4', 'request_amount': 120
})

# 单张使用
ok, deducted, err = apply_voucher(sor, instance_id, customer_id, order_id, context)

# 批量使用
result = batch_apply_vouchers(sor, customer_id, order_id, [vid1, vid2], context)
# → {total_deducted, remaining, details}

accounting (账单结算联动)

# 先尝试代金券,剩余从余额扣
result = batch_apply_vouchers(sor, customer_id, order_id, voucher_ids, context)
if result['remaining'] > 0:
    accounting.deduct_balance(customer_id, result['remaining'], order_id)

客户自助查询 APIvoucher 自身提供)

GET /voucher/api/v1/available.dspy
认证: Bearer Token
参数: product_type, product_name, request_amount (均可选)
返回: {status, data: [{id, code, face_value, valid_from, valid_to, template_name}], total}

context 字段约定

字段 来源 说明
request_amount 消费金额 必须
product_type llm.catelog llm/image/video/audio
product_name 模型名 gpt-4, dall-e-3 等
user_level 客户等级 数字
valid_from/valid_to 实例字段 自动注入

外部调用 API

函数 用途
apply_voucher_api(customer_id, order_id, voucher_ids, context) 使用代金券
get_available_vouchers_api(customer_id, context) 内部查询可用券
GET /voucher/api/v1/available.dspy 远端客户查询可用券HTTP API
get_registered_rule_types() 获取规则类型列表

Pitfalls

  • 代金券一次性使用,不要追踪 remaining_value 或 partial 状态
  • 规则 config 必须是合法 JSON 字符串存储validators 中要 try/except json.loads
  • batch_apply_vouchers 按顺序尝试remaining 归零即停
  • 删除模板需级联删除规则和实例
  • rule_config 中数组字段用 JSON array不用逗号分隔字符串

仓库

  • 路径: ~/repos/voucher/
  • 远端: git@git.opencomputing.cn:yumoqing/voucher.git
  • SQL: sql/tables.sql (建表 + appcodes 初始化)
  • RBAC: scripts/load_path.py

部署清单

  1. 执行 sql/tables.sql
  2. sage/app/sage.py: from voucher.init import load_voucher + load_voucher()
  3. sage/build.sh: 安装循环添加 voucher
  4. sage/wwwroot/global_menu.ui: 添加菜单项(无条件,不放 {% if %} 中)
  5. scripts/load_path.py 注册权限
  6. 重启 Sage