Files
junhong_cmp_fiber/openspec/changes/archive/2026-01-30-remove-tier-commission-redundancy/design.md
huang 1cf17e8f14
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m46s
清理冗余的梯度返佣(TierCommission)配置
- 移除 Model 层:删除 ShopSeriesCommissionTier 模型及相关字段
- 更新 DTO:删除 TierCommissionConfig、TierEntry 类型及相关请求/响应字段
- 删除 Store 层:移除 ShopSeriesCommissionTierStore 及相关查询逻辑
- 简化 Service 层:删除梯度返佣处理逻辑,统计查询移除 tier_bonus 字段
- 数据库迁移:创建 000034_remove_tier_commission 移除相关表和字段
- 更新测试:移除梯度返佣相关测试用例,更新集成测试
- OpenAPI 文档:删除梯度返佣相关 schema 和枚举值
- 归档变更:归档 remove-tier-commission-redundancy 到 archive/2026-01-30-
- 同步规范:更新 4 个主 specs,标记废弃功能并添加迁移指引

原因:梯度返佣功能与一次性梯度佣金功能重复,且从未实现实际计算逻辑
迁移:使用一次性佣金的梯度模式 (OneTimeCommissionConfig.type = "tiered") 替代
2026-01-30 14:57:24 +08:00

356 lines
12 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.
## Context
当前系统中存在两套梯度佣金配置机制:
1. **TierCommission (梯度返佣)**:通过 `tb_shop_series_commission_tier` 表存储,支持按周期(月/季/年)和类型(销量/销售额)设置梯度奖励
2. **OneTimeCommission.tiered (一次性梯度佣金)**:通过 `tb_shop_series_one_time_commission_tier` 表存储,支持按销量或销售额设置一次性梯度奖励
通过代码探索发现:
- `TierCommission` 有完整的数据库表、Model、DTO、Store 定义
- 但在 `commission_calculation` 服务中**没有实际的计算逻辑**
- `CommissionSourceTierBonus` 常量被定义但从未在佣金计算中使用
- 统计查询中预留了 `tier_bonus_amount` 等字段,但永远为 0
实际业务需求是:**基础返佣(成本价差)+ 一次性佣金(固定或梯度)** 两种机制。
由于系统尚未上线,现在是清理冗余代码的最佳时机。
## Goals / Non-Goals
**Goals:**
- 删除所有与 `TierCommission` (梯度返佣) 相关的代码和数据库结构
- 简化佣金配置模型,只保留基础返佣和一次性佣金两种机制
- 更新 API 文档和集成测试,确保 API 契约清晰
- 确保佣金计算逻辑继续正常工作(不受删除影响)
**Non-Goals:**
- 不修改一次性佣金的现有逻辑OneTimeCommission 保持不变)
- 不修改基础返佣的现有逻辑base_commission 保持不变)
- 不涉及数据迁移(系统未上线,无历史数据)
- 不重构佣金计算的核心流程
## Decisions
### Decision 1: 数据库迁移策略
**选择**: 创建新的 migration 文件删除表和字段
**理由**:
- 系统未上线,无需保留历史数据
- 使用标准的 migration 流程便于版本控制和回滚
- 迁移文件编号使用下一个递增编号(查看 `migrations/` 目录获取最新编号)
**替代方案及其劣势**:
- ❌ 直接修改现有 migration 文件:违反 migration 不可变原则
- ❌ 手动执行 SQL缺乏版本控制团队协作困难
**Migration 内容**:
```sql
-- up migration
ALTER TABLE tb_shop_series_allocation DROP COLUMN IF EXISTS enable_tier_commission;
ALTER TABLE tb_shop_series_allocation_config DROP COLUMN IF EXISTS enable_tier_commission;
DROP TABLE IF EXISTS tb_shop_series_commission_tier;
-- down migration (恢复结构,用于紧急回滚)
CREATE TABLE IF NOT EXISTS tb_shop_series_commission_tier (...);
ALTER TABLE tb_shop_series_allocation ADD COLUMN enable_tier_commission BOOLEAN DEFAULT FALSE;
ALTER TABLE tb_shop_series_allocation_config ADD COLUMN enable_tier_commission BOOLEAN;
```
---
### Decision 2: DTO 字段删除策略
**选择**: 直接删除 `TierCommissionConfig``TierEntry` 类型,以及所有引用这些类型的字段
**理由**:
- 系统未上线,无 API 兼容性负担
- 清晰的 API 契约更利于前端开发
- 避免"字段存在但不可用"的混淆状态
**替代方案及其劣势**:
- ❌ 保留字段但标记为 deprecated增加维护成本前端可能误用
- ❌ 使用 API 版本控制v2过度设计系统尚未发布 v1
**影响的 DTO**:
- `CreateShopSeriesAllocationRequest`: 删除 `EnableTierCommission``TierConfig` 字段
- `UpdateShopSeriesAllocationRequest`: 删除 `EnableTierCommission``TierConfig` 字段
- `ShopSeriesAllocationResponse`: 删除 `EnableTierCommission` 字段
- `TierCommissionConfig``TierEntry`: 整个类型删除
---
### Decision 3: Store 层清理策略
**选择**: 完全删除 `ShopSeriesCommissionTierStore` 及其实现
**理由**:
- 该 Store 没有被任何业务逻辑调用
- 删除后减少依赖注入复杂度
- 避免未来误用
**需要修改的依赖注入位置**:
- `internal/bootstrap/wire.go` (或依赖注入配置文件):删除 `ShopSeriesCommissionTierStore` 的 provider
- `internal/service/shop_series_allocation/service.go`:删除结构体中的 `tierStore` 字段(如果存在)
---
### Decision 4: 常量和枚举清理策略
**选择**: 删除 `CommissionSourceTierBonus` 常量,更新所有相关注释和文档
**理由**:
- 该常量从未在佣金计算中使用
- 保留会误导开发者以为该功能可用
- 佣金来源枚举简化为两个值:`cost_diff``one_time`
**需要更新的位置**:
- `internal/model/commission.go`: 删除 `CommissionSourceTierBonus` 常量定义
- `migrations/000029_add_one_time_commission.up.sql`: 更新 `commission_source` 字段注释
- 所有相关的 API 文档和 DTO 注释
---
### Decision 5: 统计查询更新策略
**选择**: 删除统计查询中的 `tier_bonus` 相关字段和 SQL 逻辑
**理由**:
- 这些字段永远为 0无实际价值
- 简化 SQL 查询提升性能
- 减少前端展示的无用信息
**需要修改的位置**:
- `internal/store/postgres/commission_record_store.go`:
- 删除 `TierBonusAmount``TierBonusCount` 字段定义
- 删除 SQL 中的 `COALESCE(SUM(CASE WHEN commission_source = 'tier_bonus' ...))` 语句
- `internal/model/dto/commission.go`:
- 删除 `CommissionStatsResponse` 中的 `TierBonusAmount``TierBonusCount``TierBonusPercent` 字段
- `internal/service/my_commission/service.go`:
- 删除 `tierBonusPercent` 的计算逻辑
---
### Decision 6: 测试更新策略
**选择**: 删除所有与 `enable_tier_commission` 相关的测试用例,添加验证佣金来源枚举的测试
**理由**:
- 测试应反映实际业务需求
- 删除无效测试提高测试套件可维护性
- 添加枚举验证测试确保不会误用 `tier_bonus`
**需要修改的测试**:
- `tests/integration/shop_series_allocation_test.go`: 删除包含 `enable_tier_commission` 的测试场景
- `tests/integration/shop_package_batch_allocation_test.go`: 删除 tier_config 相关的测试数据
- 添加新测试:验证创建 `commission_source = "tier_bonus"` 的佣金记录会失败
---
### Decision 7: Service 层清理策略
**选择**: 删除 `shop_series_allocation` Service 中处理 `tier_config` 的逻辑
**理由**:
- Service 层应只处理有效的业务逻辑
- 删除无用代码降低认知负担
**需要修改的位置**:
- `internal/service/shop_series_allocation/service.go`:
- 删除 `validateTierConfig()` 方法(如果存在)
- 删除创建/更新分配时对 `TierConfig` 的处理逻辑
- 删除 `tierStore` 的依赖注入字段
---
### Decision 8: 验证逻辑更新
**选择**: 更新 DTO 验证规则,确保不接受 `tier_bonus` 作为佣金来源
**理由**:
- 在 API 入口层就拦截无效输入
- 提供清晰的错误提示
**实现方式**:
- 使用 Validator 的 `oneof` 标签限制 `commission_source` 只能是 `cost_diff``one_time`
-`CommissionRecordListRequest` 等 DTO 中更新验证规则
## Risks / Trade-offs
### Risk 1: 误删除正在使用的代码
**风险**: 虽然探索显示 `TierCommission` 未被使用,但可能有未被发现的引用
**缓解措施**:
- 在删除前使用 IDE 的 "Find Usages" 功能全局搜索所有引用
- 运行完整的测试套件确保没有编译错误
- 代码审查时重点检查删除的影响范围
- 保留完整的 git 历史,必要时可快速回滚
---
### Risk 2: API 契约变更可能影响前端开发
**风险**: 前端可能已经基于旧的 API 文档开发
**缓解措施**:
- 与前端团队同步变更内容
- 更新 OpenAPI 文档并生成新的 TypeScript 类型定义
- 由于系统未上线,前端调整成本较低
---
### Risk 3: Migration 执行失败
**风险**: 删除表/字段的 migration 可能因数据库权限或锁问题失败
**缓解措施**:
- 在开发环境先测试 migration
- 使用 `DROP ... IF EXISTS` 避免重复执行报错
- 提供完整的 down migration 支持回滚
- 记录执行步骤和常见问题排查指南
---
### Risk 4: 佣金统计查询变更可能影响性能
**风险**: 删除 SQL 中的 `tier_bonus` 分支后,查询性能可能有微小波动
**缓解措施**:
- 简化 SQL 逻辑理论上会提升性能
- 在测试环境执行性能测试对比
- 监控线上查询耗时(虽然系统未上线,为未来做准备)
**Trade-off**:
- 获得:更简洁的代码和更快的统计查询
- 失去:未来如果需要重新引入梯度返佣,需要重新实现(但根据业务需求,这种可能性很低)
## Migration Plan
### Phase 1: 代码清理(本地开发)
1. **删除 Model 和 DTO**
- 删除 `internal/model/shop_series_commission_tier.go`
- 更新 `internal/model/dto/shop_series_allocation.go`
- 更新 `internal/model/dto/commission.go`
- 删除 `internal/model/commission.go` 中的 `CommissionSourceTierBonus`
2. **删除 Store 层**
- 删除 `internal/store/postgres/shop_series_commission_tier_store.go`
- 删除 `internal/store/interface.go` 中的 `ShopSeriesCommissionTierStore` 接口定义
- 更新 `internal/store/postgres/commission_record_store.go` 的统计查询
3. **更新 Service 层**
- 更新 `internal/service/shop_series_allocation/service.go`
- 更新 `internal/service/my_commission/service.go`
- 删除依赖注入中的 `tierStore` 引用
4. **更新 Handler 层**
- 更新 `internal/handler/shop_series_allocation_handler.go`(如有必要)
5. **更新依赖注入**
- 更新 `internal/bootstrap/wire.go` 或相关配置文件
6. **运行测试验证**
```bash
go test ./...
```
### Phase 2: 数据库迁移(本地验证)
1. **创建 migration 文件**
- 查看 `migrations/` 目录最新编号
- 创建新的 migration 文件(如 `000030_remove_tier_commission.up.sql`
2. **本地执行 migration**
```bash
go run cmd/migrate/main.go up
```
3. **验证数据库结构**
```sql
\d tb_shop_series_allocation
\d tb_shop_series_allocation_config
\dt tb_shop_series_commission_tier -- 应返回不存在
```
### Phase 3: 测试更新(本地验证)
1. **删除无效测试**
- 更新 `tests/integration/shop_series_allocation_test.go`
- 更新 `tests/integration/shop_package_batch_allocation_test.go`
2. **添加验证测试**
- 添加测试验证 `commission_source = "tier_bonus"` 被拒绝
3. **运行完整测试套件**
```bash
go test -v ./tests/integration/...
```
### Phase 4: 文档更新
1. **更新 OpenAPI 文档**
- 删除 `TierCommissionConfig` schema
- 更新受影响的 API 端点定义
2. **生成新的文档**
```bash
make generate-docs # 或相应的命令
```
### Phase 5: 代码审查和合并
1. **提交 Pull Request**
- 标题:`清理冗余的梯度返佣(TierCommission)配置`
- 描述:引用 proposal 和 design 文档
2. **代码审查重点**
- 确认所有引用都已删除
- 验证测试覆盖率
- 检查 migration 正确性
3. **合并到主分支**
### Phase 6: 部署(未来上线时)
1. **开发环境验证**
2. **测试环境验证**
3. **生产环境部署**(虽然当前系统未上线)
### Rollback Strategy
如果发现问题需要回滚:
1. **代码回滚**
```bash
git revert <commit-hash>
```
2. **数据库回滚**
```bash
go run cmd/migrate/main.go down
```
3. **验证回滚成功**
- 运行测试套件
- 检查数据库结构恢复
## Open Questions
1. **是否需要通知前端团队**
- 状态:待确认
- 建议:由于 API 契约变更,应提前同步
2. **是否需要在变更日志中记录此次清理**
- 状态:待确认
- 建议:记录在 CHANGELOG.md 中,标记为 "BREAKING CHANGE"(虽然系统未上线)
3. **OpenAPI 文档的更新流程是什么**
- 状态:待确认
- 需要了解项目中是如何生成和维护 OpenAPI 文档的
4. **是否有其他依赖于 `tb_shop_series_commission_tier` 表的外部系统**
- 状态:待确认
- 建议:检查是否有数据分析、报表系统等外部依赖