Files
junhong_cmp_fiber/openspec/specs/one-time-commission-trigger/spec.md
huang b9733c4913
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m12s
fix: 修正零售价架构错误 + 清理旧微信配置 + 归档提案 + 前端接口文档
1. 修正 retail_price 架构:
   - 删除 batch-pricing 接口的 pricing_target 字段和 retail_price 分支
     (上级只能改下级成本价,不能改零售价)
   - 新增 PATCH /api/admin/packages/:id/retail-price 接口
     (代理自己改自己的零售价,校验 retail_price >= cost_price)

2. 清理旧微信 YAML 配置(已全部迁移到数据库 tb_wechat_config):
   - 删除 config.yaml 中 wechat.official_account 配置节
   - 删除 NewOfficialAccountApp() 旧工厂函数
   - 清理 personal_customer service 中的死代码(旧登录/绑定微信方法)
   - 清理 docker-compose.prod.yml 中旧微信环境变量和证书挂载注释

3. 归档四个已完成提案到 openspec/changes/archive/

4. 新增前端接口变更说明文档(docs/前端接口变更说明.md)

5. 修正归档提案和 specs 中关于 pricing_target 的错误描述
2026-03-19 17:39:43 +08:00

163 lines
6.2 KiB
Markdown
Raw 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.
# one-time-commission-trigger Specification
## Purpose
一次性佣金触发机制 - 定义单次充值和累计充值两种触发条件、佣金发放规则、配置获取和幂等性保障。
## Requirements
### Requirement: 一次性充值触发佣金
系统 SHALL 支持"一次性充值"触发条件:当单笔订单金额 ≥ 配置阈值时触发一次性佣金。
#### Scenario: 达到一次性充值阈值
- **WHEN** 订单金额 500 元,配置阈值 300 元,该卡未发放过一次性佣金
- **THEN** 系统发放一次性佣金,标记卡的 first_commission_paid 为 true
#### Scenario: 未达到阈值
- **WHEN** 订单金额 200 元,配置阈值 300 元
- **THEN** 系统不发放一次性佣金
#### Scenario: 已发放过一次性佣金
- **WHEN** 订单金额 500 元,但卡的 first_commission_paid 已为 true
- **THEN** 系统不重复发放一次性佣金
---
### Requirement: 累计充值触发佣金
系统 SHALL 支持"累计充值"触发条件:当卡/设备的累计充值金额 ≥ 配置阈值时触发一次性佣金。
**关键修复**:每次支付成功后必须更新累计充值金额,确保累计值能正确递增并达到阈值。
#### Scenario: 累计达到阈值
- **WHEN** 卡之前累计充值 200 元,本次充值 150 元,配置阈值 300 元
- **THEN** 系统更新累计充值为 350 元
- **AND** 累计 350 元 ≥ 300 元,系统发放一次性佣金
- **AND** 标记 first_commission_paid = true
#### Scenario: 累计未达到阈值
- **WHEN** 卡之前累计充值 100 元,本次充值 100 元,配置阈值 300 元
- **THEN** 系统更新累计充值为 200 元
- **AND** 累计 200 元 < 300 元,系统不发放一次性佣金
#### Scenario: 每次支付都更新累计值
- **WHEN** 卡累计充值为 50 元
- **AND** 连续发生 3 次充值100 元、150 元、80 元
- **THEN** 第 1 次充值后累计 150 元
- **AND** 第 2 次充值后累计 300 元
- **AND** 第 3 次充值后累计 380 元
---
### Requirement: 一次性佣金只发放一次
每张卡/设备的一次性佣金 SHALL 只发放一次,通过 first_commission_paid 字段控制。
#### Scenario: 首次触发
- **WHEN** 首次满足触发条件
- **THEN** 发放佣金,设置 first_commission_paid = true
#### Scenario: 再次满足条件
- **WHEN** 再次满足触发条件但 first_commission_paid 已为 true
- **THEN** 不发放佣金
---
### Requirement: 一次性佣金配置获取
一次性佣金的触发条件和金额 SHALL 从 ShopSeriesAllocation 配置获取。
**关键修复**:配置必须能够通过 ShopSeriesAllocation 创建/更新接口正确落库并生效。
#### Scenario: 获取触发条件和金额
- **WHEN** 触发一次性佣金检查
- **THEN** 系统从卡关联的 ShopSeriesAllocation 获取 one_time_commission_trigger触发类型、one_time_commission_threshold阈值、one_time_commission_mode模式、one_time_commission_value金额/比例)
#### Scenario: 固定类型配置
- **WHEN** 创建 ShopSeriesAllocation 时设置 one_time_commission_type = "fixed"
- **AND** 设置 one_time_commission_mode = "fixed"one_time_commission_value = 500050 元)
- **THEN** 系统将配置正确写入数据库
- **AND** 查询该配置时能正确返回所有一次性佣金字段
#### Scenario: 梯度类型配置
- **WHEN** 创建 ShopSeriesAllocation 时设置 one_time_commission_type = "tiered"
- **AND** 提供梯度档位配置:[{threshold: 100, mode: "fixed", value: 2000}, {threshold: 300, mode: "percent", value: 10}]
- **THEN** 系统将主配置写入 tb_shop_series_allocation
- **AND** 将档位配置写入 tb_shop_series_one_time_commission_tier
- **AND** 查询该配置时能正确返回主配置和关联的档位列表
#### Scenario: 更新梯度配置
- **WHEN** 更新 ShopSeriesAllocation 的梯度配置
- **AND** 新档位配置与旧配置不同
- **THEN** 系统先删除旧档位数据WHERE allocation_id = ?
- **AND** 再批量插入新档位数据
- **AND** 查询时返回最新的档位配置
#### Scenario: 无一次性佣金配置
- **WHEN** 卡关联的系列分配未启用一次性佣金enable_one_time_commission = false
- **THEN** 不发放一次性佣金
---
### Requirement: 一次性佣金发放对象
一次性佣金 SHALL 发放给卡/设备的直接归属店铺。
#### Scenario: 发放给归属店铺
- **WHEN** 卡归属店铺 A触发一次性佣金
- **THEN** 佣金入账到店铺 A 的钱包
---
### Requirement: 配置参数校验
系统 MUST 在创建/更新 ShopSeriesAllocation 时校验一次性佣金配置的完整性。
#### Scenario: 启用一次性佣金必须提供配置
- **WHEN** 创建 ShopSeriesAllocation 时设置 enable_one_time_commission = true
- **AND** 未提供 one_time_commission_config
- **THEN** 系统返回错误:一次性佣金配置无效(错误码 40101
#### Scenario: 固定类型必须提供 mode 和 value
- **WHEN** 一次性佣金类型为 "fixed"
- **AND** one_time_commission_mode 或 one_time_commission_value 为空
- **THEN** 系统返回错误:一次性佣金模式/金额缺失(错误码 40102/40103
#### Scenario: 梯度类型必须提供 tiers
- **WHEN** 一次性佣金类型为 "tiered"
- **AND** tiers 配置为空或 null
- **THEN** 系统返回错误:梯度佣金档位配置缺失(错误码 40104
#### Scenario: 梯度档位配置校验
- **WHEN** 提供的梯度档位缺少必填字段threshold_value、commission_mode、commission_value
- **THEN** 系统返回错误:梯度佣金档位配置无效(错误码 40105
### Requirement: 一次性佣金触发条件
系统 SHALL 在满足一次性佣金阈值规则的前提下,仅对客户端订单触发一次性佣金。
完整触发判断 MUST 为:`!order.IsPurchaseOnBehalf && order.Source == "client"`
#### Scenario: 客户端自购订单触发
- **WHEN** 订单满足阈值条件,且 `order.IsPurchaseOnBehalf=false``order.Source="client"`
- **THEN** 系统 SHALL 触发一次性佣金计算
#### Scenario: 代购订单不触发
- **WHEN** 订单满足阈值条件,但 `order.IsPurchaseOnBehalf=true`
- **THEN** 系统 SHALL 不触发一次性佣金
#### Scenario: 后台订单不触发
- **WHEN** 订单满足阈值条件,且 `order.Source="admin"`
- **THEN** 系统 SHALL 不触发一次性佣金