---
phase: 03-device-system
plan: "01"
subsystem: device
tags: [migration, model, gateway, dto]
dependency_graph:
  requires: []
  provides:
    - tb_device 5个 sync-info 存储字段
    - tb_device_sim_binding.is_current 字段
    - Gateway SyncDeviceInfo() 方法
    - DeviceResponse 5个新字段
    - DeviceCardBindingResponse.IsCurrent
    - BoundCardInfo.IsCurrent
  affects:
    - Plan 03-02（依赖本 Plan 全部产出：模型字段 + Gateway 方法 + DTO 定义）
tech_stack:
  added: []
  patterns:
    - golang-migrate 迁移文件（up/down 对）
    - GORM 模型字段追加（保持 gorm tag 格式一致性）
    - Gateway 泛型 doRequestWithResponse[T] 调用模式
key_files:
  created:
    - migrations/000090_device_fields_extension.up.sql
    - migrations/000090_device_fields_extension.down.sql
    - migrations/000091_device_sim_binding_is_current.up.sql
    - migrations/000091_device_sim_binding_is_current.down.sql
  modified:
    - internal/model/device.go
    - internal/model/device_sim_binding.go
    - internal/gateway/models.go
    - internal/gateway/device.go
    - internal/model/dto/device_dto.go
    - internal/model/dto/asset_dto.go
decisions:
  - "5 个 sync-info 字段有离线存储意义（设备下线后保留最后状态），非实时字段（rssi/battery）不入库"
  - "SyncDeviceInfo 使用同步 doRequestWithResponse[T] 泛型调用，与现有 GetDeviceInfo 区分（async vs sync）"
  - "is_current 字段位于 tb_device_sim_binding，由 sync-info current_iccid 决定"
metrics:
  duration: "8min"
  completed_date: "2026-03-28"
  tasks: 2
  files: 10
---

# Phase 03 Plan 01: 设备体系数据基础层 Summary

**一句话总结：** 新增 DB 迁移扩展 tb_device（5字段）和 tb_device_sim_binding（is_current），对接 Gateway sync-info 接口，并同步扩展 Device/DeviceSimBinding 模型及 DTO。

## Tasks Completed

| Task | Name | Commit | Files |
|------|------|--------|-------|
| 1 | DB 迁移 + 模型字段扩展（D-0 + D-2 DB 层） | `42b884a` | 4 迁移文件 + 2 模型文件 |
| 2 | Gateway SyncDeviceInfo 方法 + DTO 字段扩展（D-1 + D-2 DTO 层） | `825def8` | gateway/models.go, gateway/device.go, device_dto.go, asset_dto.go |

## Artifacts Delivered

### 数据库迁移

- **000090_device_fields_extension**：tb_device 新增 `online_status`（INT DEFAULT 0）、`last_online_time`（TIMESTAMP NULL）、`software_version`（VARCHAR(100) DEFAULT ''）、`switch_mode`（VARCHAR(10) DEFAULT '0'）、`last_gateway_sync_at`（TIMESTAMP NULL）
- **000091_device_sim_binding_is_current**：tb_device_sim_binding 新增 `is_current`（BOOLEAN DEFAULT FALSE）

### 模型更新

- **Device 模型**：追加 5 个字段（OnlineStatus / LastOnlineTime / SoftwareVersion / SwitchMode / LastGatewaySyncAt）
- **DeviceSimBinding 模型**：追加 IsCurrent 字段

### Gateway 层

- **SyncDeviceInfoReq / SyncDeviceInfoResp**：18 字段的完整响应结构，支持 current_iccid / online_status / software_version / switch_mode / last_online_time 等关键字段
- **SyncDeviceInfo() 方法**：POST /device/sync-info，同步返回全量数据（区别于异步 /device/info）

### DTO 扩展

- **DeviceResponse**：新增 5 个 sync-info 字段（与模型一一对应）
- **DeviceCardBindingResponse**：新增 `IsCurrent bool`
- **BoundCardInfo**：新增 `IsCurrent bool`

## Deviations from Plan

None — 计划完全按预期执行。

## Verification

- ✅ `make migrate-version` 输出版本 91，dirty=false
- ✅ `go build ./...` 零新增编译错误
- ✅ PostgreSQL MCP 验证 tb_device 含 5 个新列
- ✅ PostgreSQL MCP 验证 tb_device_sim_binding 含 is_current
- ✅ `SyncDeviceInfo` 方法在 internal/gateway/device.go 中实现

## Self-Check: PASSED
