This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-08-31
|
||||
30
openspec/changes/add-commission-clawback-records/design.md
Normal file
30
openspec/changes/add-commission-clawback-records/design.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## Context
|
||||
|
||||
退款和佣金终态可能异步到达,回溯必须等待原佣金事实且不能修改其历史记录。
|
||||
|
||||
## Decisions
|
||||
|
||||
- 回溯表以退款+原佣金唯一,保存负数快照;退款消费者等待佣金终态再可靠重试。
|
||||
- 在钱包事务内先处理待审提现释放,再插入回溯和扣款流水;唯一约束保证重放安全。
|
||||
|
||||
## 生成、资金与读侧契约
|
||||
|
||||
### 退款事件消费
|
||||
|
||||
- 退款完成可靠事件以 `refund_id`、`order_id` 进入回溯用例;锁定退款、订单和佣金终态。原订单佣金未终态时不写“无需回溯”,仅保留可重试事件;终态无佣金时写退款已处理且无需回溯的审计;换货事件不进入本用例。
|
||||
- 查询原订单全部可回溯佣金,按稳定顺序计算。全额退款回溯每条剩余可回溯金额;部分退款以 `refund_amount / frozen_actual_paid_amount` 计算,每条向下取整,最后一条仅补足总额舍入差且不得超过该条剩余可回溯余额。冻结实收金额缺失或非正时记录可恢复失败,不以订单标价替代。
|
||||
- 新表以 `(refund_id, original_commission_id)` 唯一,保存负数金额、原佣金/订单/退款快照、不可提现标识、生成时间;唯一冲突视为已生成,禁止第二次扣款。
|
||||
|
||||
### 钱包与提现原子边界
|
||||
|
||||
- 在同一钱包事务内,先锁定代理佣金钱包和所有待审核/审批中的提现申请;拒绝这些申请、释放其冻结余额并保存“退款回溯优先”原因,然后插入所有回溯明细和负数佣金钱包流水。允许钱包余额低于零。
|
||||
- 原佣金记录、历史发放金额和已提现完成事实不更新、不删除;回溯是独立负数事实。事务任一步失败时不释放提现、不写部分回溯或部分流水,可靠事件保留重试。
|
||||
|
||||
### 查询与导出
|
||||
|
||||
- 扩展佣金明细列表/详情:原佣金返回 `clawback_records` 摘要,回溯明细返回 `original_commission_id`、退款单号、负数金额、不可提现、回溯后实际钱包余额和生成时间。关联查询先应用既有佣金数据范围,再按关联 ID 查询;越权不泄露存在性。
|
||||
- 导出每条原佣金和回溯明细各一行,冻结筛选、操作者、可见范围和生成时间;金额保持分,展示层转换元不得改变负数或余额事实。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
新增成对迁移;隔离库验证全额/部分、舍入、佣金延迟、重复事件、提现释放、负余额及 up/down/up。
|
||||
25
openspec/changes/add-commission-clawback-records/proposal.md
Normal file
25
openspec/changes/add-commission-clawback-records/proposal.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Scope
|
||||
|
||||
- 迭代编号:`AUG26-012`。
|
||||
|
||||
## Why
|
||||
|
||||
套餐退款后佣金需以独立负数事实回溯,并与提现冻结和钱包余额一致。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增不可提现负数回溯明细及原佣金/退款关联。
|
||||
- 按冻结实收比例、舍入和幂等规则扣回佣金。
|
||||
- 回溯前释放待审提现,允许佣金钱包负余额。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- 无。
|
||||
|
||||
### Modified Capabilities
|
||||
- `agent-funds-commission`: 退款佣金回溯。
|
||||
|
||||
## Impact
|
||||
|
||||
影响退款事件、佣金明细、钱包、提现和 Schema。
|
||||
@@ -0,0 +1,23 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 套餐退款佣金回溯
|
||||
系统 SHALL 在套餐退款后保留原佣金不变,并创建关联原佣金记录和退款单的负数、不可提现回溯明细,冻结原订单号及原佣金关键字段。同一退款业务必须幂等;若佣金计算未终态则等待终态后生成,确认无佣金才标记无需回溯。换货不在本期范围。
|
||||
|
||||
部分退款按本次退款金额与订单冻结实收金额比例,对每条原佣金按分向下取整;最后一条补足舍入差,累计回溯不得超过原佣金。生成前系统 MUST 拒绝并释放待审核提现,再生成回溯明细和钱包扣款流水;佣金钱包允许负余额。
|
||||
|
||||
#### Scenario: 部分退款舍入
|
||||
- **WHEN** 一笔部分退款关联多条原佣金且比例计算产生分级舍入差
|
||||
- **THEN** 系统按各条向下取整并仅在最后一条补差,回溯总额等于应回溯额且不超过各原佣金可回溯余额
|
||||
|
||||
### Requirement: 回溯明细关联查询与导出
|
||||
系统 SHALL 在佣金明细中分别展示原发放佣金和回溯扣款记录,并允许从任一记录查询其关联的退款单、原佣金或全部回溯明细。回溯记录必须显示负数金额、不可提现标识、来源退款单号、原佣金记录号、生成时间和回溯后佣金钱包实际余额。佣金明细及导出 MUST 使用既有佣金数据范围:代理仅可读取自身及其既有可见范围内的事实,平台/超级管理员遵循既有范围;无权记录不得通过关联 ID、汇总或导出泄露。
|
||||
|
||||
导出应冻结筛选条件、操作者和可见范围;原佣金与回溯记录均作为独立行导出,回溯后余额为对应钱包变动提交后的实际余额,可为负数。
|
||||
|
||||
#### Scenario: 代理查询越权回溯记录
|
||||
- **WHEN** 代理使用回溯记录 ID、原佣金 ID 或退款单号查询其数据范围外的回溯关系
|
||||
- **THEN** 系统按既有数据范围返回不存在或空结果,不泄露关联事实
|
||||
|
||||
#### Scenario: 重复退款消费
|
||||
- **WHEN** 同一退款完成事件被重复消费
|
||||
- **THEN** 系统不重复生成回溯明细、钱包扣款或提现释放事实
|
||||
@@ -0,0 +1,8 @@
|
||||
## 1. 回溯实现
|
||||
- [ ] 1.1 追踪退款完成、佣金计算终态、提现冻结和佣金钱包链路。
|
||||
- [ ] 1.2 新增回溯明细、退款/原佣金唯一约束、状态/索引的成对迁移和 DTO。
|
||||
- [ ] 1.3 实现比例分摊、最后一条舍入补差、终态等待、待审提现释放、负余额扣款及幂等消费者。
|
||||
|
||||
## 2. 验证
|
||||
- [ ] 2.1 隔离库验证全额/部分、重复消费、佣金延迟、负余额和 up/down/up。
|
||||
- [ ] 2.2 运行 `gofmt -w`、`go build ./cmd/api ./cmd/worker`、`go run cmd/gendocs/main.go`、`openspec validate add-commission-clawback-records --strict` 与 `openspec doctor --json`;自动化测试按项目决策为 N/A。
|
||||
Reference in New Issue
Block a user