# Proposal: refactor-one-time-commission-allocation

**Feature ID**: feature-012-refactor-one-time-commission-allocation

## Why

当前一次性佣金架构存在概念与存储错位的问题：一次性佣金是"系列级"概念（每张卡/设备在该系列下只触发一次），但 `one_time_commission_amount` 却存储在"套餐分配"（`ShopPackageAllocation`）中。这导致：

1. **数据冗余**：同一系列的多个套餐分配时，佣金配置需要重复设置
2. **隐性假设**：代码靠"取第一个"（`GetByShopAndSeries` + `LIMIT 1`）获取佣金，假设同系列配置相同但无约束保证
3. **查询低效**：`enable` 藏在 JSON 里，无法高效查询
4. **废弃代码**：`ShopSeriesOneTimeCommissionTier` 表定义了但完全未使用

## What Changes

### 新增

- 创建 `tb_shop_series_allocation` 新表，专门管理系列分配和一次性佣金
- 新增系列分配 API（CRUD）：`/api/admin/shop-series-allocations`
- `PackageSeries` 添加 `enable_one_time_commission` 布尔字段（从 JSON 提升到顶层）

### 修改

- **BREAKING** `ShopPackageAllocation` 移除 `one_time_commission_amount` 和 `series_id` 字段，添加 `series_allocation_id` 关联
- 佣金计算逻辑改为从系列分配获取佣金配置
- 梯度模式下实现链式分配：代理能拿的金额 = min(梯度匹配金额, 上级给的上限)
- 业务流程改造：必须先分配系列，再分配套餐
- `ShopSeriesCommissionStats` 的 `allocation_id` 重新关联到系列分配

### 删除

- 删除 `ShopSeriesOneTimeCommissionTier` 表和相关代码（从未使用）
- 删除 `ShopPackageAllocationStore.GetByShopAndSeries` 方法（"取第一个"hack）

## Capabilities

### New Capabilities

- `shop-series-allocation`: 店铺系列分配模块，管理店铺对套餐系列的分配关系和一次性佣金配置

### Modified Capabilities

- `commission-calculation`: 佣金计算改用系列分配获取一次性佣金配置，梯度模式实现链式分配
- `commission-trigger`: 佣金触发时从系列分配读取佣金金额

## Impact

### 代码影响

| 模块 | 影响 |
|------|------|
| `internal/model/` | 新增 `ShopSeriesAllocation`，修改 `ShopPackageAllocation`、`PackageSeries` |
| `internal/store/postgres/` | 新增 `shop_series_allocation_store.go`，修改套餐分配和佣金相关 store |
| `internal/service/` | 新增 `shop_series_allocation/`，修改 `commission_calculation/`、`recharge/`、`order/` |
| `internal/handler/admin/` | 新增 `shop_series_allocation.go`，修改套餐分配 handler |
| `internal/router/` | 添加系列分配路由 |

### API 影响

| 类型 | 端点 | 说明 |
|------|------|------|
| 新增 | `POST /api/admin/shop-series-allocations` | 创建系列分配 |
| 新增 | `GET /api/admin/shop-series-allocations` | 查询系列分配列表 |
| 新增 | `GET /api/admin/shop-series-allocations/:id` | 获取系列分配详情 |
| 新增 | `PUT /api/admin/shop-series-allocations/:id` | 更新系列分配 |
| 新增 | `DELETE /api/admin/shop-series-allocations/:id` | 删除系列分配 |
| **BREAKING** | `POST /api/admin/shop-package-allocations` | 移除 `one_time_commission_amount` 参数 |
| **BREAKING** | `PUT /api/admin/shop-package-allocations/:id` | 移除 `one_time_commission_amount` 参数 |

### 数据库影响

- 新增表：`tb_shop_series_allocation`
- 修改表：`tb_shop_package_allocation`（删除列）、`tb_package_series`（新增列）
- 删除表：`tb_shop_series_one_time_commission_tier`

### 技术栈

- 遵循 Handler → Service → Store → Model 分层架构
- 使用 Fiber v2.x + GORM v1.25.x
- 使用新工作流生成验收测试和流程测试

### 测试计划

- 使用 `/opsx:gen-tests` 从 Spec 生成验收测试
- 覆盖系列分配 CRUD、佣金计算链式分配、业务流程约束
- 删除原有相关测试，使用新工作流测试替代

### 性能考虑

- 系列分配查询：直接通过 `shop_id + series_id` 唯一索引查询，无需 LIMIT 1
- `enable_one_time_commission` 字段可建索引，支持高效过滤
