feat: 添加设备IMEI和单卡ICCID查询接口
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled

- 新增 GET /api/admin/devices/by-imei/:imei 接口,支持通过设备号查询设备详情
- 新增 GET /api/admin/iot-cards/by-iccid/:iccid 接口,支持通过ICCID查询单卡详情
- 添加对应的 Service 层方法和 Handler
- 更新 OpenAPI 文档
- 添加集成测试并修复测试环境配置(使用环境变量)
- 归档已完成的 OpenSpec 变更记录

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-27 09:59:54 +08:00
parent ce0783f96e
commit 477a9fc98d
28 changed files with 1159 additions and 19 deletions

View File

@@ -31,11 +31,25 @@ Keep this managed block so 'openspec update' can refresh the instructions.
|---------|-----------|------|
| 创建/修改 DTO 文件 | `dto-standards` | description 标签、枚举字段、验证标签规范 |
| 创建/修改 Model 模型 | `model-standards` | GORM 模型结构、字段标签、TableName 规范 |
| 注册 API 路由 | `api-routing` | Register() 函数、RouteSpec 必填项 |
| 注册 API 路由 / **新增 Handler** | `api-routing` | Register() 函数、RouteSpec、**文档生成器更新** |
| 测试接口/验证数据 | `db-validation` | PostgreSQL MCP 使用方法和验证示例 |
| 数据库迁移 | `db-migration` | 迁移命令、文件规范、执行流程、失败处理 |
| 维护规范文档 | `doc-management` | 规范文档流程和维护规则 |
### ⚠️ 新增 Handler 时必须同步更新文档生成器
新增 Handler 后,接口不会自动出现在 OpenAPI 文档中。**必须手动更新以下两个文件**
```go
// cmd/api/docs.go 和 cmd/gendocs/main.go
handlers := &bootstrap.Handlers{
// ... 添加新 Handler
NewHandler: admin.NewXxxHandler(nil),
}
```
**完整检查清单**: 参见 [`docs/api-documentation-guide.md`](docs/api-documentation-guide.md#新增-handler-检查清单)
---
## 语言要求
@@ -137,6 +151,58 @@ Handler → Service → Store → Model
- 使用 table-driven tests
- 单元测试 < 100ms集成测试 < 1s
### ⚠️ 测试真实性原则(严格遵守)
**测试必须真正验证功能,禁止绕过核心逻辑:**
| 规则 | 说明 |
|------|------|
| ❌ 禁止传递 nil 绕过依赖 | 如果功能依赖外部服务(如对象存储、第三方 API测试必须验证该依赖的调用 |
| ❌ 禁止只测试部分流程 | 如果功能包含 A → B → C 三步,不能只测试 B 而跳过 A 和 C |
| ❌ 禁止声称"测试通过"但未验证核心逻辑 | 测试通过必须意味着功能真正可用 |
| ❌ 禁止擅自使用 Mock | 尽量使用真实服务进行集成测试,如需使用 Mock 必须先询问用户并获得同意 |
| ✅ 必须验证端到端流程 | 新增功能必须有完整的集成测试覆盖整个调用链 |
| ✅ 缺少配置时必须询问 | 如果测试需要的配置(如 API Key、环境变量缺失必须询问用户而非跳过测试 |
**反面案例**
```go
// ❌ 错误:传递 nil 绕过 storageService只测试了 processImport
handler := NewIotCardImportHandler(db, redis, store1, store2, nil, logger)
result := handler.processImport(ctx, task) // 跳过了 downloadAndParseCSV
// ✅ 正确:使用真实服务测试完整流程
handler := NewIotCardImportHandler(db, redis, store1, store2, realStorageService, logger)
handler.HandleIotCardImport(ctx, asynqTask) // 测试完整流程,验证真实上传/下载
```
**测试超时 = 生产超时**
- 集成测试超时意味着生产环境也可能超时
- 发现超时必须排查原因,不能简单跳过或增加超时时间
### 测试连接管理(必读)
**详细规范**: [docs/testing/test-connection-guide.md](docs/testing/test-connection-guide.md)
**标准模板**:
```go
func TestXxx(t *testing.T) {
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
store := postgres.NewXxxStore(tx, rdb)
// 测试代码...
}
```
**核心函数**:
- `NewTestTransaction(t)`: 创建测试事务,自动回滚
- `GetTestRedis(t)`: 获取全局 Redis 连接
- `CleanTestRedisKeys(t, rdb)`: 自动清理测试 Redis 键
**禁止使用(已移除)**:
-`SetupTestDB` / `TeardownTestDB` / `SetupTestDBWithStore`
## 性能要求
- API P95 响应时间 < 200ms
@@ -179,4 +245,20 @@ Handler → Service → Store → Model
8. ✅ 文档更新计划
9. ✅ 中文优先
### ⚠️ 任务执行规范(必须遵守)
**提案中的 tasks.md 是契约,不可擅自变更:**
| 规则 | 说明 |
|------|------|
| ❌ 禁止跳过任务 | 每个任务都是经过规划的,不能因为"简单"或"显而易见"而跳过 |
| ❌ 禁止简化任务 | 不能将多个任务合并或简化执行,除非获得明确许可 |
| ❌ 禁止自作主张优化 | 发现可以优化的地方,必须先询问是否可以调整 |
| ✅ 必须逐项完成 | 按照 tasks.md 中的顺序逐一执行并标记完成 |
| ✅ 必须询问后变更 | 如需调整任务(简化/跳过/合并/优化),先询问用户确认 |
**询问示例**
> "我注意到任务 2.1 和 2.2 可以合并为一步完成,是否可以这样优化?"
> "任务 3.1 在当前实现中可能不需要,是否可以跳过?"
**详细规范和 OpenSpec 工作流请查看**: `@/openspec/AGENTS.md`