Hermes Agent e8860401bc feat: 产品模块完整功能实现 — 资源绑定/多供应商路由/包月订购/消耗引擎/成本计算
新增模型: product_resource, product_resource_supplier, product_subscription, product_usage_log
新增API: 15个.dspy端点(资源绑定/供应商管理/订购/超额/消耗/统计)
新增UI: 4个管理界面(资源绑定/供应商关联/订购管理/消费记录)
核心逻辑: ProductManager新增 bind/unbind/subscribe/product_use/check_quota 等完整业务方法
设计文档: DESIGN.md 完整架构规范
2026-06-20 12:10:32 +08:00

479 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 产品模块 + 供应链模块 功能设计规范
> 版本: 1.0 | 日期: 2026-06-19
> 模块: product_management + supplychain
---
## 一、总体架构
```
平台方(owner)
├── product_management ← 产品目录层(定义+展示+消费)
│ ├── 产品分类树 (product_category)
│ ├── 产品注册 (product)
│ ├── 产品资源绑定 (product_resource + product_resource_supplier)
│ ├── 客户订购 (product_subscription)
│ └── 消费记录 (product_usage_log)
└── supplychain ← 供应链层(供应+定价+结算)
├── 供应商 (suppliers)
├── 供销关系 (platform_supply_relations)
├── 供销产品 (platform_supply_products)
├── 供应商资源定价 (supplier_resource_price) ← NEW
├── 分销协议 (distribution_agreements + items)
├── 销售记账 (sales_ledger)
└── 对账结算 (provider_reconcile / reseller_reconcile)
```
**职责边界:**
- product_management: 产品是什么、挂哪里、卖多少、客户买了什么、用了多少、成本多少
- supplychain: 谁来供货、供货价多少、分销折扣、对账结算
**数据流向:**
```
供应商资源定价(supplychain) → 产品资源绑定(product_mgmt) → 消费成本计算(product_mgmt) → 销售记账(supplychain) → 对账结算(supplychain)
```
---
## 二、新增数据模型
### 2.1 product_management 新增表
#### product_resource (产品资源绑定表)
产品绑定的底层资源,一个产品可绑定多个资源。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | VARCHAR(32) PK | 主键 |
| product_id | VARCHAR(32) | 产品ID → product.id |
| resource_type | VARCHAR(32) | 资源类型: llm_model/llm_monthly/compute |
| resource_ref_id | VARCHAR(32) | 资源引用ID (如 llm.id) |
| resource_ref_name | VARCHAR(255) | 资源显示名(冗余,展示用) |
| quota | DOUBLE(15,4) | 配额量(包月类用), 0=不限 |
| quota_unit | VARCHAR(32) | 配额单位: tokens/requests/gpu_hours |
| priority | INT | 多供应商时的优先级(1=最高) |
| overflow_product_id | VARCHAR(32) | 超额后转用的按量产品ID |
| status | CHAR(1) | 1=启用 0=禁用 |
| created_at | DATETIME | |
| updated_at | DATETIME | |
索引: idx_pr_product(product_id), idx_pr_resource(resource_type,resource_ref_id)
#### product_resource_supplier (产品资源-供应商关联表)
同一产品资源可关联多个供应商,按优先级路由消耗。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | VARCHAR(32) PK | 主键 |
| product_resource_id | VARCHAR(32) | → product_resource.id |
| supplier_org_id | VARCHAR(32) | 供应商机构ID → organization.id |
| priority | INT | 优先级(1=最高,消耗时优先用高优先级供应商) |
| weight | INT | 权重(priority相同时按权重分配) |
| status | CHAR(1) | 1=启用 0=禁用 |
| created_at | DATETIME | |
索引: idx_prs_resource(product_resource_id), UNIQUE idx_prs_unique(product_resource_id,supplier_org_id)
#### product_subscription (客户订购表)
客户购买包月/包量产品后的订购记录。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | VARCHAR(32) PK | 主键 |
| product_id | VARCHAR(32) | → product.id |
| user_id | VARCHAR(32) | 客户用户ID |
| user_org_id | VARCHAR(32) | 客户机构ID |
| subscription_type | CHAR(1) | 1=包月 2=包量 3=一次性 |
| status | CHAR(1) | 1=活跃 2=已过期 3=已取消 4=已超额 |
| start_date | DATE | 生效日期 |
| end_date | DATE | 到期日期 |
| quota_total | DOUBLE(15,4) | 总配额 |
| quota_used | DOUBLE(15,4) | 已使用量 |
| quota_unit | VARCHAR(32) | 配额单位 |
| overflow_mode | CHAR(1) | 超额模式: 1=转按量 2=停服 |
| overflow_rate | DOUBLE(15,6) | 超额后单价(转按量时) |
| purchase_price | DOUBLE(15,2) | 购买价格 |
| purchase_currency | CHAR(8) | 货币 |
| created_at | DATETIME | |
| updated_at | DATETIME | |
索引: idx_ps_product(product_id), idx_ps_user(user_id,user_org_id), idx_ps_status(status), idx_ps_dates(start_date,end_date)
#### product_usage_log (产品消费记录表)
每次资源消耗的详细记录,含成本精确计算。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | VARCHAR(32) PK | 主键 |
| product_id | VARCHAR(32) | → product.id |
| subscription_id | VARCHAR(32) | → product_subscription.id (可空,按量产品无订购) |
| user_id | VARCHAR(32) | 消费者用户ID |
| user_org_id | VARCHAR(32) | 消费者机构ID |
| product_resource_id | VARCHAR(32) | → product_resource.id |
| supplier_org_id | VARCHAR(32) | 实际供应商机构ID |
| resource_type | VARCHAR(32) | 资源类型 |
| resource_ref_id | VARCHAR(32) | 资源引用ID |
| used_amount | DOUBLE(15,4) | 消耗量 |
| used_unit | VARCHAR(32) | 消耗单位 |
| unit_cost | DOUBLE(15,8) | 单位成本(来自supplier_resource_price) |
| total_cost | DOUBLE(15,6) | 总成本 = used_amount × unit_cost |
| sell_price | DOUBLE(15,6) | 客户侧售价 |
| billing_mode | CHAR(1) | 1=配额内 2=超额按量 |
| source_ref_table | VARCHAR(64) | 来源表(如llmusage) |
| source_ref_id | VARCHAR(32) | 来源记录ID |
| use_time | DATETIME | 消费时间 |
| created_at | DATETIME | |
索引: idx_pul_product(product_id), idx_pul_subscription(subscription_id), idx_pul_user(user_id,user_org_id), idx_pul_supplier(supplier_org_id), idx_pul_time(use_time)
### 2.2 supplychain 新增表
#### supplier_resource_price (供应商资源定价表)
供应商对各资源的基准定价,是成本计算的源头。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | VARCHAR(32) PK | 主键 |
| supplier_org_id | VARCHAR(32) | 供应商机构ID |
| resource_type | VARCHAR(32) | 资源类型 |
| resource_ref_id | VARCHAR(32) | 资源引用ID (如 llm.id) |
| resource_ref_name | VARCHAR(255) | 资源名称(冗余) |
| unit_price | DOUBLE(15,8) | 单位价格 |
| price_unit | VARCHAR(32) | 价格单位: per_1k_tokens/per_request/per_gpu_hour |
| input_price | DOUBLE(15,8) | 输入价格(LLM专用,可空) |
| output_price | DOUBLE(15,8) | 输出价格(LLM专用,可空) |
| currency | CHAR(8) | 货币 CNY/USD |
| effective_date | DATE | 生效日期 |
| expiry_date | DATE | 失效日期(可空=长期有效) |
| status | CHAR(1) | 1=有效 0=无效 |
| created_at | DATETIME | |
| updated_at | DATETIME | |
索引: idx_srp_supplier(supplier_org_id), idx_srp_resource(resource_type,resource_ref_id), idx_srp_dates(effective_date,expiry_date), UNIQUE idx_srp_unique(supplier_org_id,resource_type,resource_ref_id,effective_date)
---
## 三、appcodes 初始化数据
```
resource_type:
llm_model = 大模型按量
llm_monthly = 大模型包月
compute = 算力
quota_unit / price_unit:
tokens = tokens
requests = 次
gpu_hours = GPU时
per_1k_tokens = 每千tokens
per_request = 每次
per_gpu_hour = 每GPU时
subscription_status:
1 = 活跃
2 = 已过期
3 = 已取消
4 = 已超额(转按量)
overflow_mode:
1 = 转按量
2 = 停服
billing_mode:
1 = 配额内
2 = 超额按量
```
---
## 四、功能清单与实现逻辑
### 模块A: product_management (产品目录层)
#### A1. 产品资源绑定管理 (管理端)
| 功能 | API | 逻辑 |
|------|-----|------|
| 查看产品的资源绑定列表 | GET /api/product_resources?product_id=X | 查 product_resource WHERE product_id=X, JOIN product_resource_supplier 获取供应商列表 |
| 为产品绑定资源 | POST /api/product_resource_bind | 插入 product_resource + 校验 product 存在且属于当前 org |
| 解绑资源 | DELETE /api/product_resource_unbind?id=X | 删除 product_resource + 级联删除 product_resource_supplier |
| 添加供应商到资源绑定 | POST /api/resource_supplier_add | 插入 product_resource_supplier, 校验 supplier_org_id 在 supplychain.suppliers 中存在 |
| 移除供应商 | DELETE /api/resource_supplier_remove?id=X | 删除 product_resource_supplier |
| 调整供应商优先级 | PUT /api/resource_supplier_priority | 更新 priority/weight |
| 设置超额产品 | PUT /api/resource_overflow | 更新 product_resource.overflow_product_id |
#### A2. 客户订购 (管理端创建 + 客户端查看)
| 功能 | API | 逻辑 |
|------|-----|------|
| 创建订购(客户购买包月产品) | POST /api/subscribe | 1.校验产品存在+状态+日期范围 2.读取product_resource获取quota 3.插入product_subscription(status=1) 4.设置overflow_rate(从超额产品的price取) |
| 查看订购列表(管理端) | GET /api/subscriptions | 查 product_subscription, 可按user_id/product_id/status筛选 |
| 查看我的订购(客户端) | GET /api/my_subscriptions | 查 product_subscription WHERE user_id=当前用户 |
| 订购详情 | GET /api/subscription_detail?id=X | 返回订购信息 + 配额使用百分比 + 关联产品信息 |
| 取消订购 | PUT /api/subscription_cancel?id=X | status改为3, 停止配额使用 |
#### A3. 产品消费 (核心引擎)
| 功能 | API | 逻辑 |
|------|-----|------|
| 消费资源 | POST /api/product_use | **核心流程(见下方详细逻辑)** |
| 查看消费记录 | GET /api/usage_logs | 查 product_usage_log, 支持按product_id/user_id/日期/供应商筛选 |
| 消费统计 | GET /api/usage_stats | 聚合查询: 按产品/供应商/日期汇总消耗量和成本 |
| 配额检查 | GET /api/quota_check?subscription_id=X | 返回 quota_total/quota_used/remaining/percentage |
**product_use 核心流程:**
```
1. 接收参数: product_id, user_id, user_org_id, used_amount, used_unit,
source_ref_table, source_ref_id, resource_ref_id
2. 查找产品: product WHERE id=product_id AND status='1'
3. 判断产品类型:
IF product_type 是包月类(llm_monthly):
a. 查找活跃订购: product_subscription WHERE product_id AND user_id
AND status='1' AND start_date<=today AND end_date>=today
b. 如果有活跃订购:
- 计算剩余配额 = quota_total - quota_used
- IF used_amount <= 剩余:
billing_mode = '1'(配额内)
unit_cost = 0 (配额内不计单次成本)
更新 quota_used += used_amount
- ELSE (超额):
先用完配额: quota_used = quota_total
超额部分 = used_amount - 剩余
billing_mode = '2'(超额按量)
查找 overflow_product 获取 overflow_rate
sell_price = 超额部分 × overflow_rate
subscription.status = '4'(已超额)
c. 如果无活跃订购(已过期/未订购):
billing_mode = '2'
按产品自身 price 计算
ELSE (按量产品):
billing_mode = '2'
直接按量计费
4. 路由供应商(确定成本来源):
查找 product_resource WHERE product_id AND resource_ref_id
查找 product_resource_supplier WHERE product_resource_id AND status='1'
ORDER BY priority ASC, weight DESC
选择第一个可用供应商 → supplier_org_id
5. 计算成本:
查找 supplier_resource_price WHERE supplier_org_id AND resource_ref_id
AND effective_date<=today AND (expiry_date IS NULL OR expiry_date>=today)
unit_cost = supplier_resource_price.unit_price (或 input_price/output_price)
total_cost = used_amount × unit_cost
6. 计算售价(给客户的计费):
按量产品: sell_price = used_amount × product.price
包月超额: sell_price = 超额部分 × subscription.overflow_rate
7. 写入 product_usage_log
8. 返回: {success, billing_mode, used_amount, total_cost, sell_price,
supplier_org_id, remaining_quota}
```
#### A4. 产品目录展示 (面向客户端)
| 功能 | API | 逻辑 |
|------|-----|------|
| 分类树(客户端) | GET /api/public_categories | 现有 get_category_tree, 只返回 status='1' AND has_product='1' 的叶子节点 |
| 分类下产品列表 | GET /api/public_products?category_id=X | 现有 get_products_by_category, 返回产品摘要+价格+是否有资源绑定 |
| 产品详情 | GET /api/public_product_detail?id=X | 现有 get_product_detail, 增加资源绑定信息(绑定了几种资源,各多少配额) |
### 模块B: supplychain (供应链层)
#### B1. 供应商资源定价管理
| 功能 | API | 逻辑 |
|------|-----|------|
| 查看供应商资源定价列表 | GET /api/supplier_resource_prices | 查 supplier_resource_price, 可按supplier_org_id/resource_type筛选 |
| 创建/更新定价 | POST /api/supplier_resource_price_save | UPSERT supplier_resource_price, 校验supplier存在 |
| 删除定价(置为无效) | DELETE /api/supplier_resource_price_disable?id=X | status改为'0' |
| 批量导入定价 | POST /api/supplier_resource_price_import | 接收JSON数组,批量插入 |
| 查询指定资源的供应商价格 | GET /api/resource_supplier_cost?resource_type=X&resource_ref_id=Y | 返回所有供应商对该资源的定价,用于成本比较 |
#### B2. 消费成本对账 (连接 product_management 和 supplychain)
| 功能 | API | 逻辑 |
|------|-----|------|
| 按供应商汇总成本 | GET /api/cost_by_supplier | 跨库JOIN: product_usage_log GROUP BY supplier_org_id, SUM(total_cost) |
| 按产品汇总成本 | GET /api/cost_by_product | product_usage_log GROUP BY product_id |
| 生成销售记账条目 | POST /api/generate_sales_ledger | 从 product_usage_log 汇总后写入 sales_ledger (周期任务或手动触发) |
| 成本趋势 | GET /api/cost_trend | 按日期汇总成本, 最近30天 |
---
## 五、业务流程推演
### 场景1: 大模型按量产品
```
1. 供应商(OpenAI代理商)在 supplychain 注册,
在 supplier_resource_price 设置 GPT-4 价格:
input_price=0.03/1Ktokens, output_price=0.06/1Ktokens
2. 平台在 product_management 创建产品:
product: "GPT-4智能对话" product_type=llm_model price=0.05/1Ktokens
3. 产品绑定资源:
product_resource: resource_type=llm_model, resource_ref_id=llm.id(GPT-4)
product_resource_supplier: supplier_org_id=OpenAI代理商, priority=1
4. 客户调用GPT-4, 消耗2000 tokens:
product_use → 路由到OpenAI代理商
unit_cost = 0.03/1K × 2 = 0.06 (成本)
sell_price = 0.05/1K × 2 = 0.10 (售价)
写入 product_usage_log
5. 月末对账:
supplychain 从 product_usage_log 汇总:
供应商: OpenAI代理商, 总成本 = SUM(total_cost)
→ 写入 sales_ledger → 供应商结算
```
### 场景2: 大模型包月产品 + 超额转按量
```
1. 平台创建包月产品:
product: "AI助手月度套餐" product_type=llm_monthly price=99.00/月
2. 产品绑定资源:
product_resource: resource_type=llm_monthly, resource_ref_id=llm.id,
quota=1000000(100万tokens), quota_unit=tokens,
overflow_product_id=指向"GPT-4按量产品"
3. 绑定两个供应商(同资源多供应商):
product_resource_supplier:
- supplier_A: priority=1, weight=70
- supplier_B: priority=1, weight=30
4. 客户购买:
product_subscription: quota_total=1000000, start=2026-06-01, end=2026-06-30
5. 客户使用中(配额内):
每次调用 → billing_mode='1', 更新 quota_used
按 weight 比例分配供应商: 70%走A, 30%走B
成本分别按各供应商的 supplier_resource_price 计算
6. 配额用完(第25天用完100万tokens):
subscription.status → '4'(已超额)
后续调用 → billing_mode='2'
sell_price = 超额量 × overflow_rate(从overflow_product的price取)
total_cost = 超额量 × supplier_unit_price(实时成本)
7. 月末: 订购到期 → 定时任务将 status='1' 且 end_date<today 的改为 '2'(已过期)
客户可选择续费(创建新subscription)
```
### 场景3: 算力产品
```
1. 供应商设置GPU定价:
supplier_resource_price: resource_type=compute, resource_ref_id=gpu_a100,
unit_price=8.00/gpu_hour
2. 平台创建算力产品:
product: "A100 GPU租用" product_type=compute, price=12.00/gpu_hour
3. 客户购买后使用 10 GPU时:
total_cost = 10 × 8.00 = 80.00
sell_price = 10 × 12.00 = 120.00
profit = 40.00
```
### 场景4: 分销商定价
```
1. 平台(owner)创建产品和资源绑定
2. 分销商通过 supplychain.distribution_agreement_items 设置自己的折扣:
discount=0.85 → 客户按 85折 购买
sale_price = product.price × 0.85
3. 客户通过分销商购买:
售价 = product.price × distribution_discount
分销商成本 = product.price × supply_discount (从supplychain取)
利润 = 售价 - 成本
4. 对账时:
sales_ledger 记录 supply_amount(进货成本) + distribution_amount(分销收入) + profit_amount
```
---
## 六、UI 页面规划
### product_management (管理端)
| 页面 | 功能 |
|------|------|
| product_resource_list/index.ui | 选择产品 → 显示/管理该产品的资源绑定 |
| product_resource_list/bind_resource.ui | 绑定资源弹窗(选资源类型+引用+配额) |
| product_resource_list/supplier_bind.ui | 为资源绑定添加/管理供应商 |
| subscription_list/index.ui | 订购列表(筛选产品/用户/状态) |
| subscription_detail.ui | 订购详情(配额进度条+消费记录) |
### product_management (客户端/展示端)
| 页面 | 功能 |
|------|------|
| (复用现有) index.ui → category树 → product列表 | 展示产品目录 |
| product_detail.ui | 产品详情(含资源信息+价格+购买按钮) |
| my_subscriptions.ui | 我的订购(配额进度+消费记录) |
### supplychain (管理端)
| 页面 | 功能 |
|------|------|
| supplier_resource_price_list/index.ui | 供应商资源定价CRUD |
| cost_dashboard.ui | 成本分析看板(按供应商/产品/日期) |
---
## 七、跨模块数据访问
| 场景 | 读 | 写 |
|------|-----|-----|
| product_use计算成本 | supplychain.supplier_resource_price | product_management.product_usage_log, product_subscription |
| 供应商定价查询 | supplychain.supplier_resource_price | - |
| 生成sales_ledger | product_management.product_usage_log | supplychain.sales_ledger |
| 供应商列表(绑定供应商时) | supplychain.suppliers | - |
| LLM模型列表(绑定资源时) | llmage.llm | - |
---
## 八、定时任务
| 任务 | 周期 | 逻辑 |
|------|------|------|
| 订购过期检查 | 每日00:05 | product_subscription WHERE status='1' AND end_date<today status='2' |
| 成本汇总入账 | 每月1日 | 上月 product_usage_log 汇总 写入 sales_ledger |
---
## 九、检查清单
- [ ] product_resource model.json + DDL
- [ ] product_resource_supplier model.json + DDL
- [ ] product_subscription model.json + DDL
- [ ] product_usage_log model.json + DDL
- [ ] supplier_resource_price model.json + DDL (supplychain)
- [ ] appcodes init data 更新
- [ ] 资源绑定 CRUD APIs (6个)
- [ ] 订购 APIs (5个)
- [ ] 消费引擎 product_use (核心)
- [ ] 消费记录查询/统计 APIs (3个)
- [ ] 供应商资源定价 CRUD APIs (5个)
- [ ] 成本对账 APIs (4个)
- [ ] 管理端 UI (5个页面)
- [ ] 客户端 UI (2个页面)
- [ ] 供应商定价 UI (2个页面)
- [ ] 定时任务 (2个)
- [ ] 集成测试: 按量产品完整流程
- [ ] 集成测试: 包月产品完整流程(含超额转按量)
- [ ] 集成测试: 多供应商路由
- [ ] 集成测试: 分销商折扣