重构: 店铺套餐分配系统从加价模式改为返佣模式
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m18s

主要变更:
- 重构分配模型:从加价模式(pricing_mode/pricing_value)改为返佣模式(base_commission + tier_commission)
- 删除独立的 my_package 接口,统一到 /api/admin/packages(通过数据权限自动过滤)
- 新增批量分配和批量调价功能,支持事务和性能优化
- 新增配置版本管理,订单创建时锁定返佣配置
- 新增成本价历史记录,支持审计和纠纷处理
- 新增统计缓存系统(Redis + 异步任务),优化梯度返佣计算性能
- 删除冗余的梯度佣金独立 CRUD 接口(合并到分配配置中)
- 归档 3 个已完成的 OpenSpec changes 并同步 8 个新 capabilities 到 main specs

技术细节:
- 数据库迁移:000026_refactor_shop_package_allocation
- 新增 Store:AllocationConfigStore, PriceHistoryStore, CommissionStatsStore
- 新增 Service:BatchAllocationService, BatchPricingService, CommissionStatsService
- 新增异步任务:统计更新、定时同步、周期归档
- 测试覆盖:批量操作集成测试、梯度佣金 CRUD 清理验证

影响:
- API 变更:删除 4 个梯度 CRUD 接口(POST/GET/PUT/DELETE /:id/tiers)
- API 新增:批量分配、批量调价接口
- 数据模型:重构 shop_series_allocation 表结构
- 性能优化:批量操作使用 CreateInBatches,统计使用 Redis 缓存

相关文档:
- openspec/changes/archive/2026-01-28-refactor-shop-package-allocation/
- openspec/specs/agent-available-packages/
- openspec/specs/allocation-config-versioning/
- 等 8 个新 capability specs
This commit is contained in:
2026-01-28 17:11:55 +08:00
parent 23eb0307bb
commit 1da680a790
97 changed files with 6810 additions and 3622 deletions

View File

@@ -0,0 +1,169 @@
## Context
### 当前状态
项目存在三种不同的测试基础设施方式:
| 方式 | 使用文件 | 问题 |
|------|---------|------|
| **testcontainers** | `role_test.go` | 需要 Docker启动慢30s+/测试CI 环境复杂 |
| **共享数据库 + DELETE** | `shop_management_test.go` 等 | 清理不可靠,数据残留,并行冲突 |
| **事务隔离** | 部分单元测试 | ✅ 正确方式,已有 `testutils.NewTestTransaction` |
### 现有基础设施
`tests/testutils/db.go` 已提供:
- `GetTestDB(t)` - 全局单例数据库连接
- `NewTestTransaction(t)` - 创建自动回滚的测试事务
- `GetTestRedis(t)` - 全局单例 Redis 连接
- `CleanTestRedisKeys(t, rdb)` - 自动清理测试 Redis 键
问题是**集成测试没有使用这些工具**,而是各自实现了不同的方式。
## Goals / Non-Goals
**Goals:**
- 统一所有集成测试使用事务隔离模式
- 移除 testcontainers 依赖,简化测试环境要求
- 消除 DELETE 清理代码,改用事务自动回滚
- 提供标准化的集成测试环境设置模式
- 确保测试可以并行运行且互不干扰
**Non-Goals:**
- 不改变测试的业务逻辑验证内容
- 不引入新的测试框架或依赖
- 不修改 `testutils` 的核心 API仅增强
- 不处理性能测试或压力测试场景
## Decisions
### 决策 1统一使用事务隔离模式
**选择**: 所有集成测试使用 `testutils.NewTestTransaction(t)` 获取独立事务
**理由**:
- 已有成熟实现,无需重新开发
- 事务回滚比 DELETE 快 100 倍以上
- 完全隔离,支持并行执行
- 不需要 Docker降低环境要求
**放弃的替代方案**:
- testcontainers启动慢、需要 Docker、CI 配置复杂
- 共享数据库 + 命名前缀:清理不可靠、并行时冲突
### 决策 2增强 testutils 支持集成测试
**选择**: 在 `testutils` 包中添加集成测试专用的辅助函数
新增函数:
```go
// NewIntegrationTestEnv 创建集成测试环境
// 包含事务、Redis、Logger、TokenManager、App
func NewIntegrationTestEnv(t *testing.T) *IntegrationTestEnv
// IntegrationTestEnv 集成测试环境
type IntegrationTestEnv struct {
TX *gorm.DB // 自动回滚的事务
Redis *redis.Client // 全局 Redis 连接
Logger *zap.Logger // 测试用 Logger
TokenManager *auth.TokenManager
App *fiber.App // 配置好的 Fiber App
}
```
**理由**:
- 减少每个测试文件的重复代码
- 统一 ErrorHandler、中间件配置
- 方便后续扩展
### 决策 3测试数据生成策略
**选择**: 使用原子计数器 + 时间戳生成唯一标识
```go
// 已有实现,继续使用
testutils.GenerateUniquePhone() // 138 + 时间戳后8位
testutil.GenerateUniqueUsername(prefix) // prefix_counter
```
**理由**:
- 即使并行运行也不会冲突
- 不依赖随机数(可重现)
- 已有实现,经过验证
### 决策 4Fiber App 配置统一
**选择**: 在 `IntegrationTestEnv` 中预配置标准的 Fiber App
配置内容:
- `ErrorHandler`: 使用 `errors.SafeErrorHandler`
- 中间件: 认证中间件(模拟用户上下文)
- 路由: 使用 `routes.RegisterRoutes` 注册
**理由**:
- 与生产环境配置一致
- 避免每个测试文件重复配置
- 便于测试真实的错误处理逻辑
## Risks / Trade-offs
### 风险 1重构范围大
**风险**: 涉及 15-20 个测试文件,可能引入新 bug
**缓解**:
- 逐个文件重构,每个文件重构后立即验证
- 保留原有测试用例逻辑,只改变环境设置方式
- 使用 `git diff` 确保只改变了预期的部分
### 风险 2事务隔离的限制
**风险**: 某些测试可能需要真实的数据库提交(如测试并发)
**缓解**:
- 这类测试极少,可以特殊处理
- 文档说明何时需要跳过事务隔离
### 风险 3testcontainers 测试可能测试了特定功能
**风险**: testcontainers 测试可能依赖完整的数据库生命周期
**缓解**:
- 分析每个 testcontainers 测试的实际需求
- 大多数只需要隔离的数据库环境,事务可以满足
## Migration Plan
### 阶段 1增强 testutils1-2 小时)
1. 添加 `IntegrationTestEnv` 结构和 `NewIntegrationTestEnv` 函数
2. 添加常用的测试辅助函数(创建测试用户、生成 Token 等)
3. 编写使用文档
### 阶段 2重构 testcontainers 测试2-3 小时)
1. 重构 `role_test.go`
2. 移除 testcontainers 导入
3. 验证所有测试通过
### 阶段 3重构 DELETE 清理测试3-4 小时)
1. 重构 `shop_management_test.go`
2. 重构 `shop_account_management_test.go`
3. 重构其他使用 DELETE 清理的测试
4. 删除所有 `teardown` 中的 DELETE 语句
### 阶段 4清理和验证1 小时)
1. 移除 `go.mod` 中的 testcontainers 依赖
2. 运行全量测试验证
3. 更新测试文档
### 回滚策略
- 每个阶段完成后提交
- 如果某个阶段失败,可以 revert 到上一个阶段
- 保留原测试文件的 git 历史,方便对比
## Open Questions
1. **是否需要保留某些 testcontainers 测试?**
- 初步判断:不需要,所有测试都可以用事务隔离替代
- 需要在实施时验证
2. **并发测试如何处理?**
- 当前项目没有并发测试
- 如果未来需要,可以单独处理
3. **测试数据库的 AutoMigrate 策略?**
- 当前在 `GetTestDB` 首次调用时执行
- 可能需要扩展迁移的模型列表