diff --git a/docs/superpowers/specs/2026-08-28-pricing-enum-design.md b/docs/superpowers/specs/2026-08-28-pricing-enum-design.md index 90f21aa..74bfff4 100644 --- a/docs/superpowers/specs/2026-08-28-pricing-enum-design.md +++ b/docs/superpowers/specs/2026-08-28-pricing-enum-design.md @@ -1,7 +1,7 @@ # 定价模块计价对象枚举化与模型计价设计 -> 版本:v0.3(本期)—— 在 v0.2(无预扣)基础上,将计价对象固定枚举化 + 接入模型计价。 -> 范围:shop-user-trade **pricing 计价模块**。交付「枚举 + 配置管理 + per_1M 计算器」层;模型结算接入另期。 +> 版本:v0.3(本期)—— 在 v0.2(无预扣)基础上,将计价对象固定枚举化 + 接入模型计价与业务模块周期计价。 +> 范围:shop-user-trade **pricing 计价模块**。交付「枚举 + 配置管理 + per_1M/per_period 计算器」层;模型/业务模块结算接入另期。 > 约定:金额一律**元**(float64,DB `NUMERIC(15,2)`,2 位小数),不足 1 分向上取整(`ceilFen`)。 --- @@ -11,9 +11,10 @@ 现状(v0.2):`pricing_config` 是「一 `biz_key` → 单一 `charge_mode` + 单模式 `rules`」,只能给任意业务标识配一种计费方式。 诉求: -1. 计价对象**固定枚举**:`工作流` + `模型列表`(model-gateway 系统模型)。后端提供枚举接口,管理端为这些项配置价格标准。 +1. 计价对象**固定枚举**:`工作流` + `模型列表`(model-gateway 系统模型)+ `业务模块`(如 AI客服)。后端提供枚举接口,管理端为这些项配置价格标准。 2. 工作流可**同时配置三套价格**(per_item / per_second / per_token),创建/使用工作流时按本次执行**选择一种**扣费方式。 3. 模型计价采用 model-gateway 已有的 OpenAI 风格 `PriceConfig`(per_1M,含 match 条件、audio 变体、缓存、折扣),不同模型类型配置内容不同。 +4. 业务模块按**周期**订阅计价(按年),通用 `per_period` 建模,后续可扩月/季。 目标:模型价格**单一来源**(只配一份,工作流与直接调模型共用);计价对象枚举 = 表结构;计算器注册表统一派发。 @@ -27,13 +28,15 @@ |---|---|---| | `workflow` | `workflow` | 固定单主体,规则为三模式容器 | | `model` | model-gateway 模型 **ID** | 每个系统模型一个主体,规则为其 PriceConfig | +| `business` | 业务模块标识(如 `ai_customer_service`) | 固定写死的一组业务模块,规则为周期订阅价格 | 枚举接口 `GET /pricing/subjects` 返回全部可配置主体: - `workflow`(静态,恒有,附 `chargeModes: [per_item, per_second, per_token]`) - 各系统模型(**实时**调 model-gateway `/listModelManage`,`system_model=true` 过滤,返回 modelId/modelName/modelType) +- 各业务模块(静态写死,如 AI客服,附 `chargeModes: [per_period]`) - 每项附 `hasConfig` + `enabled`,管理端据此区分未配价主体。 -模型主体以 **modelId** 标识(稳定不变),枚举同时返回 modelName 供展示。 +模型主体以 **modelId** 标识(稳定不变),枚举同时返回 modelName 供展示。业务模块列表固定写死在 `consts/pricing`(新增业务模块改常量,暂不做管理端增删)。 --- @@ -49,8 +52,8 @@ CREATE TABLE IF NOT EXISTS pricing_config ( creator VARCHAR(64) NOT NULL DEFAULT '', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updater VARCHAR(64) NOT NULL DEFAULT '', updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at timestamp(6), - subject_type VARCHAR(16) NOT NULL, -- workflow | model - subject_id VARCHAR(64) NOT NULL, -- workflow | model-gateway 模型ID + subject_type VARCHAR(16) NOT NULL, -- workflow | model | business + subject_id VARCHAR(64) NOT NULL, -- workflow | model-gateway 模型ID | 业务模块标识 rules TEXT NOT NULL, -- 见 §4 min_balance NUMERIC(15,2) NOT NULL DEFAULT 0, -- 门禁(元),0=不校验 currency VARCHAR(16) NOT NULL DEFAULT 'CNY', @@ -69,8 +72,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_pricing_config_subject ON pricing_config(su -- 唯一幂等键:uk_charge_order_subject (subject_type, subject_id, biz_order_no) subject_type VARCHAR(16) NOT NULL, subject_id VARCHAR(64) NOT NULL, -charge_mode VARCHAR(32) NOT NULL, -- 建单时选中/派发键:per_item/per_second/per_token/per_1K/per_1M/per_1 -rule_snapshot TEXT NOT NULL, -- workflow: 选中模式的规则片段;model: 整个 PriceConfig +charge_mode VARCHAR(32) NOT NULL, -- 建单时选中/派发键:per_item/per_second/per_token/per_1K/per_1M/per_1/per_period +rule_snapshot TEXT NOT NULL, -- workflow: 选中模式的规则片段;model: 整个 PriceConfig;business: 周期价格规则 -- 其余字段(user_id/status/actual_amount/usage/settle_time 等)不变 ``` @@ -113,6 +116,16 @@ rule_snapshot TEXT NOT NULL, -- workflow: 选中模式的规则片段 - 字段与 model-gateway `entity.PriceConfig / PriceRule / PriceMatch / PriceDiscount` 完全一致。 - Save 校验:`unit ∈ {per_1K, per_1M, per_1}`、rules 数组结构、match 字段类型(audio/video/reasoning 不同模型类型内容不同,但结构统一)。 +### 4.3 business —— 周期订阅(per_period) + +```json +{ "period": "year", "price": 1999 } +``` + +- `period`:周期单位,本期 `year`,后续可扩 `month/quarter` 等(扩值即支持,计算器按允许集合校验)。 +- `price`:每周期价格(元),一次性收取。 +- Save 校验:`period ∈ 允许集合`(本期 `{year}`)、`price > 0`。 + --- ## 5. 计算器注册表(charge_calc.go) @@ -120,7 +133,7 @@ rule_snapshot TEXT NOT NULL, -- workflow: 选中模式的规则片段 ### 5.1 统一 charge_mode 枚举 ``` -per_item | per_second | per_token | per_1K | per_1M | per_1 +per_item | per_second | per_token | per_1K | per_1M | per_1 | per_period ``` ### 5.2 新增 per_1K/per_1M/per_1 计算器(一个实现注册三个键) @@ -152,6 +165,11 @@ type ChargeUsage struct { > ⚠️ **设计决策**:per_token **费率不冻结在 rule_snapshot**(建单时未知会用哪些模型),结算时按模型 subject **实时价格**算。这是「模型价格单一来源」的代价,与 v0.2「改价不影响在途单」的 rule_snapshot 保证有冲突,仅 per_token 模式例外,其余模式仍走快照。 +### 5.5 新增 per_period 计算器(周期订阅) + +- `validate`:`period ∈ 允许集合`(本期 `{year}`)+ `price > 0`。 +- `charge`:返回 `ceilFen(price)`(每次购买按整周期一次性收取,与用量无关;`usage.ItemCount` 预留多条数叠加)。 + --- ## 6. 接口设计 @@ -160,7 +178,7 @@ type ChargeUsage struct { | 路由 | 方法 | 说明 | |---|---|---| -| `/pricing/subjects` | GET | 枚举:workflow + 实时 model-gateway 系统模型,每项附 hasConfig/enabled | +| `/pricing/subjects` | GET | 枚举:workflow + 实时 model-gateway 系统模型 + 业务模块,每项附 hasConfig/enabled | | `/pricing/config/save` | POST | `{subjectType, subjectId, rules, minBalance, currency, enabled}`,按 subject_type 校验 rules | | `/pricing/config/get` | GET | 按 subjectType+subjectId | | `/pricing/config/list` | GET | 分页,可按 subjectType/enabled 过滤 | @@ -169,19 +187,20 @@ type ChargeUsage struct { | 路由 | 方法 | 说明 | |---|---|---| -| `/pricing/open_order` | POST | `{userId, subjectType, subjectId, chargeMode?, bizOrderNo}`;workflow 的 chargeMode 必填且须已配置;model 的 chargeMode 可空(默认取 unit) | +| `/pricing/open_order` | POST | `{userId, subjectType, subjectId, chargeMode?, bizOrderNo}`;workflow 的 chargeMode 必填且须已配置;model 的 chargeMode 可空(默认取 unit);business 的 chargeMode 可空(默认 per_period) | | `/pricing/settle` `/cancel` `/fail` `/order` | — | 契约字段同步换 subjectType/subjectId | **OpenOrder 校验**: - workflow:`chargeMode ∈ rules 的 key`;`rule_snapshot = rules[chargeMode]` - model:`charge_mode = config.unit`;`rule_snapshot = 整个 PriceConfig` +- business:`charge_mode = per_period`;`rule_snapshot = 周期规则 JSON` - 门禁 `min_balance` 照旧;建单前校验规则 JSON;幂等返回既有单。 --- ## 7. 枚举实现(subject_service.go,新) -- `GET /pricing/subjects`:consul 解析 model-gateway 服务地址 → 调 `GET /listModelManage`(`system_model=true`)→ 合并固定 workflow 项。 +- `GET /pricing/subjects`:consul 解析 model-gateway 服务地址 → 调 `GET /listModelManage`(`system_model=true`)→ 合并固定 workflow 项 + 固定业务模块组(`consts/pricing`)。 - 每项查 `pricing_config` 是否已存在(hasConfig / enabled)。 - model-gateway 服务地址与鉴权放 `config.yml`(复用 `common/http` + consul 解析,同 market_service 调订单服务的模式)。 - model-gateway 不可用时:枚举接口**直接报错**(管理端低频接口,失败暴露更清晰,可重试);workflow 项仍为固定返回。 @@ -199,12 +218,15 @@ type ChargeUsage struct { | pricing_config 去 charge_mode 列 | rules 自描述,workflow 三模式都在 rules 里 | | 未配价模型按 0 计 | 工作流可含未单独配价的模型,不阻塞结算 | | min_balance 门禁照旧 | 非冻结门禁语义不变 | +| 业务模块固定写死(AI客服等) | 与「固定枚举」一致;新增业务模块改常量,暂不做管理端增删 | +| 周期计费用 per_period 通用建模 | 扩月/季只扩 period 允许集合,不改代码结构 | --- ## 9. 遗留(另期) - 模型 subject 结算接入:ai-agent 上报模型用量(PromptTokens/CompletionTokens/CachedTokens/MediaType)→ open_order/settle。 +- 业务模块订阅购买流程接入(按周期下单/扣费/续费)。 - model-gateway 停扣(切换时机沿用 v0.2 §8.2)。 - 工作流侧「选择本次扣费方式」的 UI/配置项(ai-agent 侧,本期不动)。 @@ -212,16 +234,16 @@ type ChargeUsage struct { ## 10. 改动清单 -1. `consts/pricing/charge_mode.go`:加 `per_1K/per_1M/per_1` -2. `consts/pricing/subject.go`(新):subject_type 常量 workflow/model +1. `consts/pricing/charge_mode.go`:加 `per_1K/per_1M/per_1/per_period`(含 period 允许集合 `{year}`) +2. `consts/pricing/subject.go`(新):subject_type 常量 workflow/model/business + 业务模块固定列表(AI客服 → `ai_customer_service`) 3. `model/entity/pricing/pricing_config.go`:biz_key/charge_mode → subject_type/subject_id 4. `model/dto/pricing/config_dto.go`:Save/Get/List/Info 换 subject 字段 5. `model/dto/pricing/charge_dto.go`:OpenOrderReq 加 subjectType/subjectId/chargeMode;ChargeOrderInfo 的 bizKey → subjectType/subjectId;DAO 入参同步 6. `dao/pricing/pricing_config_dao.go`:Get/Save/List 按 (subject_type, subject_id) 7. `dao/pricing/charge_order_dao.go`:幂等键改 (subject_type, subject_id, biz_order_no) -8. `service/pricing/charge_calc.go`:per_unit 计算器 + ChargeUsage 扩展 + per_token 语义改模型价 -9. `service/pricing/pricing_service.go`:OpenOrder 校验 chargeMode/unit;Save 按类型校验 rules;settleOrder 派发 -10. `service/pricing/subject_service.go`(新):枚举接口 +8. `service/pricing/charge_calc.go`:per_unit 计算器 + per_period 计算器 + ChargeUsage 扩展 + per_token 语义改模型价 +9. `service/pricing/pricing_service.go`:OpenOrder 校验 chargeMode/unit/period;Save 按类型校验 rules;settleOrder 派发 +10. `service/pricing/subject_service.go`(新):枚举接口(workflow + 实时模型 + 固定业务模块) 11. `controller/pricing/pricing_controller.go`:加 Subjects 12. `init.sql`:pricing_config 改结构、charge_order 改键、迁移 SQL 13. `config.yml`:加 model-gateway 服务地址 diff --git a/docs/superpowers/specs/pricing-config-preview.html b/docs/superpowers/specs/pricing-config-preview.html new file mode 100644 index 0000000..0ebb152 --- /dev/null +++ b/docs/superpowers/specs/pricing-config-preview.html @@ -0,0 +1,469 @@ + + + + + +计价配置管理 · 原型预览 + + + + +
+

计价配置管理 /pricing · 原型预览

+ 原型预览 · 静态无后端 +
+ +
+ + + + + +
+
+
+
工作流
+
subjectType=workflow · subjectId=workflow
+
+
+ + +
+
+ + + + + + + + + + + + +
+
+ +
+ + + + \ No newline at end of file