# 实现任务清单

## 1. 数据库迁移

- [x] 1.1 创建迁移文件 `migrations/000019_fix_device_sim_binding_constraints.up.sql`
  - 使用 `CREATE INDEX CONCURRENTLY` 添加 `idx_active_device_slot` 部分唯一索引
  - 为 `tb_device_import_task` 表添加 `warning_count` 和 `warning_items` 字段
- [x] 1.2 创建回滚文件 `migrations/000019_fix_device_sim_binding_constraints.down.sql`
- [x] 1.3 执行迁移并验证索引创建成功

## 2. 模型层修改

- [x] 2.1 创建 `internal/model/device_sim_binding.go` 文件
  - 从 `internal/model/package.go` 移动 `DeviceSimBinding` 结构体和 `TableName()` 方法
  - 确保所有 import 和 tag 正确
- [x] 2.2 从 `internal/model/package.go` 中删除 `DeviceSimBinding` 相关代码
- [x] 2.3 修改 `internal/model/device_import_task.go`
  - 添加 `WarningCount int` 字段
  - 添加 `WarningItems ImportResultItems` 字段（JSONB 类型）
- [x] 2.4 运行 `go build ./...` 确保编译通过

## 3. Store 层修改

- [x] 3.1 修改 `internal/store/postgres/device_sim_binding_store.go`
  - 添加 `isUniqueViolation(err error) bool` 辅助函数
  - 修改 `Create` 方法，检测唯一约束冲突并返回友好的业务错误
  - 根据违反的约束名（`idx_active_device_slot` 或 `idx_device_sim_bindings_active_card`）返回不同的错误信息
- [x] 3.2 添加 `github.com/jackc/pgx/v5/pgconn` 依赖（如果尚未存在）

## 4. Service 层修改

- [x] 4.1 修改 `internal/service/device/binding.go`
  - `BindCard` 方法已有应用层检查，无需修改
  - Store 层的错误处理已足够，Service 层只需透传错误

## 5. 设备导入任务修改

- [x] 5.1 修改 `internal/task/device_import.go` 中的 `deviceImportResult` 结构体
  - 添加 `warningCount int` 字段
  - 添加 `warningItems model.ImportResultItems` 字段
- [x] 5.2 修改 `processBatch` 函数添加归属权校验
  - 在 ICCID 验证循环中添加 `card.ShopID != nil` 检查
  - 如果卡已分配给店铺，记录原因 `ICCID+"已分配给店铺,不能绑定到平台库存设备"`
- [x] 5.3 修改 `processBatch` 函数添加部分成功处理逻辑
  - 当 `len(validCardIDs) > 0 && len(cardIssues) > 0` 时，设备创建后记录到 `warningItems`
  - 增加 `warningCount`
- [x] 5.4 修改 `HandleDeviceImport` 函数
  - 更新调用 `h.importTaskStore.UpdateResult` 传入 `warning_count` 和 `warning_items`
- [x] 5.5 修改 `internal/store/postgres/device_import_task_store.go`
  - 更新 `UpdateResult` 方法签名，添加 `warningCount` 和 `warningItems` 参数
  - 更新 SQL 语句保存新字段

## 6. 测试

- [x] 6.1 编写 `internal/store/postgres/device_sim_binding_store_test.go` 并发绑定测试
  - 测试同一张卡并发绑定到不同设备
  - 测试同一设备插槽并发绑定不同卡
  - 验证返回正确的错误信息
- [x] 6.2 编写 `internal/task/device_import_test.go` 归属权校验测试
  - 测试绑定平台库存卡成功
  - 测试绑定已分配店铺的卡失败
  - 测试部分成功场景，验证 warning_items 记录正确
- [x] 6.3 运行现有测试确保无回归 `go test ./...`
  - 注：tests/unit 和 tests/integration 中存在既有问题（与本次实现无关）
  - 本次实现相关测试全部通过（internal/store/postgres、internal/task）

## 7. 验证与文档

- [x] 7.1 使用 PostgreSQL MCP 验证数据库约束生效
  - 手动测试插入重复 (device_id, slot_position, bind_status=1) 记录被拒绝
  - 手动测试插入重复 (iot_card_id, bind_status=1) 记录被拒绝
- [x] 7.2 验证 API 响应结构
  - 确认设备导入任务结果包含 `warning_count` 和 `warning_items` 字段
  - 更新了 DTO 和 Service 层映射
- [x] 7.3 更新相关文档（如有必要）
  - 本次实现无需额外文档更新
