重构: 将卡/设备的套餐系列绑定从分配ID改为系列ID
- 数据库: 重命名 series_allocation_id → series_id - Model: IotCard 和 Device 字段重命名 - DTO: 所有请求/响应字段统一为 series_id - Store: 方法重命名,新增 GetByShopAndSeries 查询 - Service: 业务逻辑优化,系列验证和权限验证分离 - 测试: 更新所有测试用例,新增 shop_series_allocation_store_test.go - 文档: 更新 API 文档说明参数变更 BREAKING CHANGE: API 参数从 series_allocation_id 改为 series_id
This commit is contained in:
191
openspec/changes/refactor-series-binding-to-series-id/tasks.md
Normal file
191
openspec/changes/refactor-series-binding-to-series-id/tasks.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Tasks: refactor-series-binding-to-series-id
|
||||
|
||||
## 1. 数据库迁移
|
||||
|
||||
- [x] 1.1 创建数据库迁移文件 `migrations/000XXX_refactor_series_binding_to_series_id.up.sql`,重命名 `tb_iot_card.series_allocation_id` 为 `series_id`,`tb_device.series_allocation_id` 为 `series_id`,更新字段注释
|
||||
- [x] 1.2 创建回滚迁移文件 `migrations/000XXX_refactor_series_binding_to_series_id.down.sql`
|
||||
- [x] 1.3 验证索引是否存在:检查 `tb_shop_series_allocation` 是否有 `(shop_id, series_id)` 复合索引,如不存在则添加
|
||||
- [x] 1.4 执行迁移:运行 `migrate up`,验证字段重命名成功,无错误
|
||||
|
||||
## 2. Model 层修改
|
||||
|
||||
- [x] 2.1 修改 `internal/model/iot_card.go`:将 `SeriesAllocationID` 字段重命名为 `SeriesID`,更新 gorm 标签和注释
|
||||
- [x] 2.2 修改 `internal/model/device.go`:将 `SeriesAllocationID` 字段重命名为 `SeriesID`,更新 gorm 标签和注释
|
||||
- [x] 2.3 验证编译:运行 `go build ./internal/model/...`,确认无编译错误
|
||||
|
||||
## 3. DTO 层修改
|
||||
|
||||
- [x] 3.1 修改 `internal/model/dto/iot_card_dto.go`:更新 `ListStandaloneIotCardRequest` 的查询参数 `SeriesAllocationID` → `SeriesID`
|
||||
- [x] 3.2 修改 `internal/model/dto/iot_card_dto.go`:更新 `StandaloneIotCardResponse` 的响应字段 `SeriesAllocationID` → `SeriesID`
|
||||
- [x] 3.3 修改 `internal/model/dto/iot_card_dto.go`:更新 `BatchSetCardSeriesBindngRequest` 的请求字段 `SeriesAllocationID` → `SeriesID`,更新 description 为 "套餐系列ID(0表示清除关联)"
|
||||
- [x] 3.4 修改 `internal/model/dto/device_dto.go`:更新 `ListDeviceRequest` 的查询参数 `SeriesAllocationID` → `SeriesID`
|
||||
- [x] 3.5 修改 `internal/model/dto/device_dto.go`:更新 `DeviceResponse` 的响应字段 `SeriesAllocationID` → `SeriesID`
|
||||
- [x] 3.6 修改 `internal/model/dto/device_dto.go`:更新 `BatchSetDeviceSeriesBindngRequest` 的请求字段 `SeriesAllocationID` → `SeriesID`,更新 description 为 "套餐系列ID(0表示清除关联)"
|
||||
- [x] 3.7 验证编译:运行 `go build ./internal/model/dto/...`,确认无编译错误
|
||||
|
||||
## 4. Store 层修改
|
||||
|
||||
- [x] 4.1 修改 `internal/store/postgres/iot_card_store.go`:更新 `ListStandalone` 方法,将过滤条件 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 4.2 修改 `internal/store/postgres/iot_card_store.go`:更新 `Count` 方法,将过滤条件 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 4.3 修改 `internal/store/postgres/iot_card_store.go`:重命名方法 `BatchUpdateSeriesAllocation` 为 `BatchUpdateSeriesID`,更新 SQL 字段名
|
||||
- [x] 4.4 修改 `internal/store/postgres/iot_card_store.go`:重命名方法 `ListBySeriesAllocationID` 为 `ListBySeriesID`,更新 WHERE 条件
|
||||
- [x] 4.5 修改 `internal/store/postgres/device_store.go`:更新 `List` 方法,将过滤条件 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 4.6 修改 `internal/store/postgres/device_store.go`:重命名方法 `BatchUpdateSeriesAllocation` 为 `BatchUpdateSeriesID`,更新 SQL 字段名
|
||||
- [x] 4.7 修改 `internal/store/postgres/device_store.go`:重命名方法 `ListBySeriesAllocationID` 为 `ListBySeriesID`,更新 WHERE 条件
|
||||
- [x] 4.8 修改 `internal/store/postgres/shop_series_allocation_store.go`:新增方法 `GetByShopAndSeries(ctx, shopID, seriesID)`,实现根据店铺和系列查询分配配置
|
||||
- [x] 4.9 验证或创建 `internal/store/postgres/package_series_store.go`:如不存在则创建,实现 `GetByID(ctx, id)` 方法
|
||||
- [x] 4.10 如果创建了新 Store,在 `internal/bootstrap/stores.go` 中注册 `PackageSeriesStore`
|
||||
- [x] 4.11 验证编译:运行 `go build ./internal/store/...`,确认无编译错误
|
||||
|
||||
## 5. Service 层修改 - iot_card
|
||||
|
||||
- [x] 5.1 修改 `internal/service/iot_card/service.go`:更新 `ListStandalone` 方法,将过滤条件 key `series_allocation_id` 改为 `series_id`
|
||||
- [x] 5.2 修改 `internal/service/iot_card/service.go`:更新 `buildStandaloneResponse` 方法,将字段 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 5.3 修改 `internal/service/iot_card/service.go`:重构 `BatchSetSeriesBinding` 方法
|
||||
- [x] 5.4 在 `internal/service/iot_card/service.go` 的 `Service` 结构体中添加 `packageSeriesStore` 依赖(如果不存在)
|
||||
- [x] 5.5 验证编译:运行 `go build ./internal/service/iot_card/...`,确认无编译错误
|
||||
- [x] 5.6 运行 `lsp_diagnostics` 检查 `internal/service/iot_card/service.go`,确认无类型错误
|
||||
|
||||
## 6. Service 层修改 - device
|
||||
|
||||
- [x] 6.1 修改 `internal/service/device/service.go`:更新 `List` 方法,将过滤条件 key `series_allocation_id` 改为 `series_id`
|
||||
- [x] 6.2 修改 `internal/service/device/service.go`:更新 `buildDeviceResponse` 方法,将字段 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 6.3 修改 `internal/service/device/service.go`:重构 `BatchSetSeriesBinding` 方法
|
||||
- [x] 6.4 在 `internal/service/device/service.go` 的 `Service` 结构体中添加 `packageSeriesStore` 依赖(如果不存在)
|
||||
- [x] 6.5 验证编译:运行 `go build ./internal/service/device/...`,确认无编译错误
|
||||
- [x] 6.6 运行 `lsp_diagnostics` 检查 `internal/service/device/service.go`,确认无类型错误
|
||||
|
||||
## 7. Service 层修改 - purchase_validation(关键)
|
||||
|
||||
- [x] 7.1 修改 `internal/service/purchase_validation/service.go`:重构 `ValidateCardPurchase` 方法
|
||||
- [x] 7.2 修改 `internal/service/purchase_validation/service.go`:重构 `ValidateDevicePurchase` 方法
|
||||
- [x] 7.3 更新 `ValidateCardPurchase` 和 `ValidateDevicePurchase` 的错误消息,从 "套餐系列分配不存在" 改为 "该卡/设备未关联套餐系列"
|
||||
- [x] 7.4 验证编译:运行 `go build ./internal/service/purchase_validation/...`,确认无编译错误
|
||||
- [x] 7.5 运行 `lsp_diagnostics` 检查 `internal/service/purchase_validation/service.go`,确认无类型错误
|
||||
|
||||
## 8. Service 层修改 - commission_calculation(关键)
|
||||
|
||||
- [x] 8.1 修改 `internal/service/commission_calculation/service.go`:重构 `CalculateOrderCommission` 方法
|
||||
- [x] 8.2 修改 `internal/service/commission_calculation/service.go`:重构 `CalculateDeviceOrderCommission` 方法(同样的逻辑)
|
||||
- [x] 8.3 验证编译:运行 `go build ./internal/service/commission_calculation/...`,确认无编译错误
|
||||
- [x] 8.4 运行 `lsp_diagnostics` 检查 `internal/service/commission_calculation/service.go`,确认无类型错误
|
||||
|
||||
## 9. Service 层修改 - recharge
|
||||
|
||||
- [x] 9.1 修改 `internal/service/recharge/service.go`:重构充值相关方法,将获取 `seriesAllocationID` 的逻辑改为直接使用 `seriesID`
|
||||
- [x] 9.2 修改 `internal/service/recharge/service.go`:更新返佣查询逻辑,使用 `GetByShopAndSeries(shopID, seriesID)` 而不是 `GetByID(allocationID)`
|
||||
- [x] 9.3 验证编译:运行 `go build ./internal/service/recharge/...`,确认无编译错误
|
||||
- [x] 9.4 运行 `lsp_diagnostics` 检查 `internal/service/recharge/service.go`,确认无类型错误
|
||||
|
||||
## 10. Service 层修改 - order
|
||||
|
||||
- [x] 10.1 检查 `internal/service/order/service.go` 中是否有直接使用 `SeriesAllocationID` 的地方,如有则更新为 `SeriesID`
|
||||
- [x] 10.2 验证编译:运行 `go build ./internal/service/order/...`,确认无编译错误
|
||||
- [x] 10.3 运行 `lsp_diagnostics` 检查 `internal/service/order/service.go`,确认无类型错误
|
||||
|
||||
## 11. Bootstrap 依赖注入
|
||||
|
||||
- [x] 11.1 如果创建了 `PackageSeriesStore`,在 `internal/bootstrap/stores.go` 中初始化并添加到 `Stores` 结构体
|
||||
- [x] 11.2 在 `internal/bootstrap/services.go` 中,为 `iot_card.Service` 和 `device.Service` 注入 `packageSeriesStore` 依赖
|
||||
- [x] 11.3 验证编译:运行 `go build ./internal/bootstrap/...`,确认无编译错误
|
||||
|
||||
## 12. Handler & Routes 层
|
||||
|
||||
- [x] 12.1 修改 `internal/routes/iot_card.go`:更新 `/series-binding` 路由的 Description,说明参数从 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 12.2 修改 `internal/routes/device.go`:更新 `/series-binding` 路由的 Description,说明参数从 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 12.3 验证 Handler 层代码:`internal/handler/admin/iot_card.go` 和 `device.go` 无需修改(使用 DTO)
|
||||
- [x] 12.4 验证编译:运行 `go build ./internal/routes/... ./internal/handler/...`,确认无编译错误
|
||||
|
||||
## 13. Store 层测试更新
|
||||
|
||||
- [x] 13.1 修改 `internal/store/postgres/iot_card_store_test.go`:更新所有测试用例,将 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 13.2 修改 `internal/store/postgres/iot_card_store_test.go`:重命名测试函数 `TestIotCardStore_ListBySeriesAllocationID` 为 `TestIotCardStore_ListBySeriesID`
|
||||
- [x] 13.3 修改 `internal/store/postgres/iot_card_store_test.go`:更新过滤条件测试,将 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 13.4 修改 `internal/store/postgres/device_store_test.go`:更新所有测试用例,将 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 13.5 修改 `internal/store/postgres/device_store_test.go`:重命名测试函数 `TestDeviceStore_ListBySeriesAllocationID` 为 `TestDeviceStore_ListBySeriesID`
|
||||
- [x] 13.6 新增测试:在 `shop_series_allocation_store_test.go` 中添加 `TestShopSeriesAllocationStore_GetByShopAndSeries` 测试
|
||||
- [x] 13.7 运行 Store 层测试:`source .env.local && go test -v ./internal/store/postgres/...`,确认全部通过
|
||||
|
||||
## 14. Service 层测试更新 - iot_card
|
||||
|
||||
- [x] 14.1 修改 `internal/service/iot_card/service_test.go`:更新 `TestIotCardService_BatchSetSeriesBinding` 测试
|
||||
- [x] 14.2 更新测试数据准备顺序:先 `PackageSeries`,再 `ShopSeriesAllocation`,最后 `IotCard`
|
||||
- [x] 14.3 运行 Service 层测试:`source .env.local && go test -v ./internal/service/iot_card/...`,确认全部通过
|
||||
|
||||
## 15. Service 层测试更新 - device
|
||||
|
||||
- [x] 15.1 修改 `internal/service/device/service_test.go`:更新 `TestDeviceService_BatchSetSeriesBinding` 测试
|
||||
- [x] 15.2 更新测试数据准备顺序:先 `PackageSeries`,再 `ShopSeriesAllocation`,最后 `Device`
|
||||
- [x] 15.3 运行 Service 层测试:`source .env.local && go test -v ./internal/service/device/...`,确认全部通过
|
||||
|
||||
## 16. Service 层测试更新 - purchase_validation
|
||||
|
||||
- [x] 16.1 修改 `internal/service/purchase_validation/service_test.go`:更新所有测试用例
|
||||
- [x] 16.2 运行 Service 层测试:`source .env.local && go test -v ./internal/service/purchase_validation/...`,确认全部通过
|
||||
|
||||
## 17. Service 层测试更新 - commission_calculation
|
||||
|
||||
- [x] 17.1 修改 `internal/service/commission_calculation/service_test.go`:更新所有测试用例
|
||||
- [x] 17.2 运行 Service 层测试:`source .env.local && go test -v ./internal/service/commission_calculation/...`,确认全部通过
|
||||
|
||||
## 18. Service 层测试更新 - recharge & order
|
||||
|
||||
- [x] 18.1 修改 `internal/service/recharge/service_test.go`:更新测试用例,将 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 18.2 修改 `internal/service/order/service_test.go`:更新测试用例,将 `SeriesAllocationID` 改为 `SeriesID`
|
||||
- [x] 18.3 运行 Service 层测试:`source .env.local && go test -v ./internal/service/recharge/... ./internal/service/order/...`,确认全部通过
|
||||
|
||||
## 19. 集成测试更新 - iot_card
|
||||
|
||||
- [x] 19.1 修改 `tests/integration/iot_card_test.go`:更新 `TestIotCard_BatchSetSeriesBinding` 测试
|
||||
- [x] 19.2 更新所有子测试用例的 JSON 请求体(约 10 个)
|
||||
- [x] 19.3 运行集成测试:`source .env.local && cd tests/integration && go test -v -run "TestIotCard_BatchSetSeriesBinding"`,确认全部通过
|
||||
|
||||
## 20. 集成测试更新 - device
|
||||
|
||||
- [x] 20.1 修改 `tests/integration/device_test.go`:更新 `TestDevice_BatchSetSeriesBinding` 测试
|
||||
- [x] 20.2 更新所有子测试用例的 JSON 请求体(约 10 个)
|
||||
- [x] 20.3 运行集成测试:`source .env.local && cd tests/integration && go test -v -run "TestDevice_BatchSetSeriesBinding"`,确认全部通过
|
||||
|
||||
## 21. 单元测试更新 - commission_calculation
|
||||
|
||||
- [x] 21.1 修改 `tests/unit/commission_calculation_service_test.go`:更新所有测试用例
|
||||
- [x] 21.2 运行单元测试:`source .env.local && go test -v ./tests/unit/...`,确认全部通过
|
||||
|
||||
## 22. 全量测试验证
|
||||
|
||||
- [x] 22.1 运行所有测试:`source .env.local && go test -v ./...`,确认全部通过,无遗漏
|
||||
- [x] 22.2 运行编译检查:`go build ./...`,确认无编译错误
|
||||
- [x] 22.3 使用 grep 搜索遗漏:`grep -r "SeriesAllocationID" internal/ --include="*.go"`,确认无遗漏
|
||||
- [x] 22.4 使用 grep 搜索遗漏:`grep -r "series_allocation_id" internal/ --include="*.go"`,确认无遗漏(仅数据库注释除外)
|
||||
|
||||
## 23. API 手动测试
|
||||
|
||||
- [ ] 23.1 启动本地服务:`go run cmd/api/main.go`
|
||||
- [ ] 23.2 测试 IoT 卡系列绑定 API:`PATCH /api/admin/iot-cards/series-binding`,使用 Postman 或 curl 发送请求,验证参数 `series_id` 生效
|
||||
- [ ] 23.3 测试设备系列绑定 API:`PATCH /api/admin/devices/series-binding`,使用 Postman 或 curl 发送请求,验证参数 `series_id` 生效
|
||||
- [ ] 23.4 测试卡列表查询:`GET /api/admin/iot-cards/standalone?series_id=1`,验证过滤生效
|
||||
- [ ] 23.5 测试设备列表查询:`GET /api/admin/devices?series_id=1`,验证过滤生效
|
||||
- [ ] 23.6 检查日志:确认无错误日志,SQL 查询使用 `series_id` 而不是 `series_allocation_id`
|
||||
|
||||
## 24. API 文档更新
|
||||
|
||||
- [x] 24.1 更新 OpenAPI 文档注释:确保路由描述中明确说明参数从 `series_allocation_id` 改为 `series_id`
|
||||
- [x] 24.2 重新生成 API 文档:运行 `go run cmd/gendocs/main.go`,生成最新的 OpenAPI spec
|
||||
- [x] 24.3 验证生成的文档:检查 `docs/admin-openapi.yaml` 中 `/iot-cards/series-binding` 和 `/devices/series-binding` 的参数定义
|
||||
- [x] 24.4 如有前端文档,更新前端接口文档,说明 BREAKING CHANGE
|
||||
|
||||
## 25. 清理和最终验证
|
||||
|
||||
- [x] 25.1 删除所有临时代码和注释
|
||||
- [x] 25.2 运行 `gofmt -w .` 格式化所有代码
|
||||
- [x] 25.3 运行 `go mod tidy` 清理依赖
|
||||
- [x] 25.4 再次运行全量测试:`source .env.local && go test -v ./...`,确认全部通过
|
||||
- [x] 25.5 使用 `git diff` 检查所有改动,确认无遗漏,无多余修改
|
||||
- [x] 25.6 更新 CHANGELOG(如有),记录 BREAKING CHANGE
|
||||
|
||||
## 26. 提交和归档
|
||||
|
||||
- [ ] 26.1 提交代码:创建 Git commit,使用中文 commit message:"重构: 将卡/设备的套餐系列绑定从分配ID改为系列ID"
|
||||
- [ ] 26.2 运行 OpenSpec 归档:`openspec archive --change refactor-series-binding-to-series-id`
|
||||
- [ ] 26.3 验证归档成功:检查 `openspec/changes/archive/` 目录,确认变更已归档
|
||||
- [ ] 26.4 清理工作目录:删除 `openspec/changes/refactor-series-binding-to-series-id/`(已归档)
|
||||
Reference in New Issue
Block a user