docs(03): capture phase context

This commit is contained in:
2026-03-28 11:16:02 +08:00
parent 4ff5dcf55e
commit ce6aa62fd6
2 changed files with 202 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
# Phase 3: 设备体系完善 - Context
**Gathered:** 2026-03-28
**Status:** Ready for planning
<domain>
## Phase Boundary
扩展设备数据模型D-0、对接 Gateway sync-info 同步接口D-1、建立"当前使用卡"标识D-2、将刷新接口接入 sync-info 完成端到端数据更新D-3
全部为修复性/完善性变更无新业务模块。仅影响设备相关模型、Gateway 客户端、资产刷新服务。
</domain>
<decisions>
## Implementation Decisions
### Plan 分组策略
- **D-01:** 拆分为 **2 个 Plan**
- **Plan 1基础层**D-0迁移+模型+DTO+ D-1Gateway SyncDeviceInfo 方法)+ D-2is_current 字段)
- **Plan 2功能层**D-3Refresh 接入 sync-info + updateDeviceFromSyncInfo
- **D-02:** Plan 1 内部执行顺序D-0 先行DB 迁移、Device Model、DeviceSimBinding Model、DTO 全部到位)→ D-1 + D-2 并行(都依赖 D-0互不依赖
- **D-03:** 每个子任务独立一个 commit延续 Phase 1/2 粒度规范)
### DB 迁移
- **D-04:** 迁移编号从 `000090` 起,拆为 2 个迁移文件:
- `000090_device_fields_extension`tb_device 新增 5 个字段
- `000091_device_sim_binding_is_current`tb_device_sim_binding 新增 is_current 字段
- **D-05:** 使用 `.up.sql` / `.down.sql` 双文件形式(与现有迁移规范一致)
### Gateway 类型定义位置
- **D-06:** `SyncDeviceInfoReq` / `SyncDeviceInfoResp` 放在 **`internal/gateway/models.go`**(与现有 DeviceInfoReq / SlotInfoResp 等结构保持风格一致)
- **D-07:** `SyncDeviceInfo()` 方法放在 `internal/gateway/device.go`(与现有 GetDeviceInfo / GetSlotInfo 等方法一起)
- 修正文档中将类型嵌入 device.go 代码片段属于示意,不代表最终位置
### 实时字段暴露范围
- **D-08:** Refresh 响应中**不暴露**非存储实时字段rssi / battery_level / ssid / wifi_enabled 等)
- **D-09:** 实时字段仅在调用 sync-info 时**写入 DB 存储字段**online_status / last_online_time / software_version / switch_mode / last_gateway_sync_at
- **D-10:** 这满足所有成功标准(标准 2、4 只要求存储字段同步)
### is_current 字段的 DTO 同步范围
- **D-11:** `is_current` 同步到**两处 DTO**
- `BoundCardInfo``internal/model/dto/asset_dto.go`)—— 资产实时状态 Refresh 响应中的绑定卡列表
- `DeviceCardBindingResponse``internal/model/dto/device_dto.go`)—— 设备管理页 ListDeviceCards 接口
- **D-12:** 两处同步,保持前端两个场景下的数据一致
### updateDeviceFromSyncInfo 实现细节
- **D-13:** `updateDeviceFromSyncInfo` 为私有函数,位于 `internal/service/asset/service.go`
- **D-14:** is_current 更新使用**事务**:先全部设为 false再把 current_iccid 对应行设为 true原子操作防止中间状态
- **D-15:** sync-info 调用失败时**不阻断刷新流程**,仅记录 Warn 日志(`sync-info 调用失败`
### Agent's Discretion
- `last_online_time` / `last_gateway_sync_at` 字段 parsingsync-info 返回字符串,需转换为 time.Time的具体格式agent 参考 Gateway 文档中的 `last_update_time` 示例格式
- `DeviceRealtimeInfo` 独立 DTO 结构**不创建**(不暴露实时字段,无需此结构)
- `updateDeviceFromSyncInfo` 的 DB 更新使用 GORM `Updates(map[string]any{...})`,不用 `Save()`(避免全字段覆写)
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### 修复规格(核心参考)
- `.sisyphus/plans/修正业务-完整方案.md` — 完整修复规格书,含每个需求的代码片段和人工验收清单:
- 方案 DDEVICE-01~04约第 955-1130 行D-0 字段策略 + D-1 Gateway 接口 + D-2 is_current + D-3 Refresh 接入)
### Gateway 接口文档
- `docs/第三方文档/gateway设备详情同步接口.md` — sync-info 接口完整字段说明data 字段映射表、cardNo 规则、认证方式)
### 需要修改的核心文件
- `internal/model/device.go` — D-0新增 5 个 DB 字段
- `internal/model/device_sim_binding.go` — D-2新增 is_current 字段
- `internal/model/dto/asset_dto.go` — D-2BoundCardInfo 新增 is_current
- `internal/model/dto/device_dto.go` — D-0DeviceResponse 新增 5 个字段D-2DeviceCardBindingResponse 新增 is_current
- `internal/gateway/models.go` — D-1新增 SyncDeviceInfoReq / SyncDeviceInfoResp
- `internal/gateway/device.go` — D-1新增 SyncDeviceInfo() 方法
- `internal/service/asset/service.go` — D-3Refresh device 分支追加 sync-info 调用;新增 updateDeviceFromSyncInfo()
- `migrations/` — D-0000090_device_fields_extensionD-2000091_device_sim_binding_is_current
### 现有参考实现
- `internal/service/asset/service.go:Refresh()` — 约第 295 行,现有 device 刷新分支(追加 sync-info 调用入口)
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- `internal/gateway/client.go:doRequestWithResponse[T]()` — 泛型请求方法SyncDeviceInfo 直接复用(与 GetDeviceInfo 相同调用模式)
- `internal/service/asset/service.go:Refresh()` — 已有 device 冷却 Key + 绑定卡遍历框架D-3 在此追加 sync-info 调用
- `internal/service/asset/service.go:deviceSimBindingStore` — 已注入D-3 的 updateDeviceFromSyncInfo 可直接使用
### Established Patterns
- Gateway 类型分离:结构体在 `models.go`方法在对应领域文件device.go / flow_card.go 等)
- DB 更新:使用 `Updates(map[string]any{...})` + `Model(&T{})` + `Where`,不用 `Save()`
- 错误处理:非关键步骤失败用 `logger.Warn`,关键步骤用 `errors.Wrap`
### Integration Points
- `internal/gateway/device.go` — 新增 SyncDeviceInfo 方法
- `internal/service/asset/service.go:Refresh()` device 分支 —— sync-info 调用入口(冷却 Key 设置之前,已遍历完绑定卡之后)
- `BoundCardInfo``asset_dto.go`(被 AssetRealtimeStatusResponse 引用,多个 C 端和 B 端接口共用)
</code_context>
<specifics>
## Specific Ideas
- 修正文档中 D-3 的代码片段提供了 `updateDeviceFromSyncInfo` 的函数骨架agent 应直接参考(文件:`.sisyphus/plans/修正业务-完整方案.md` 方案 D-3 段落)
- `SyncDeviceInfoResp.LastOnlineTime` 字段类型用 `string`Gateway 返回字符串),在 updateDeviceFromSyncInfo 内按需 Parse
</specifics>
<deferred>
## Deferred Ideas
- 设备实时字段rssi / battery_level / ssid 等)暴露到 Refresh 响应 —— 超出当前成功标准,考虑 Phase 4+ 或按需补充
- DeviceRealtimeInfo 独立 DTO 结构 —— 若未来暴露实时字段时再创建
</deferred>
---
*Phase: 03-device-system*
*Context gathered: 2026-03-28*

View File

@@ -0,0 +1,70 @@
# Phase 3: 设备体系完善 - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-03-28
**Phase:** 03-device-system
**Areas discussed:** Plan 分组策略, 实时字段暴露范围, is_current DTO 同步范围, Gateway 类型定义位置
---
## Plan 分组策略
| Option | Description | Selected |
|--------|-------------|----------|
| 2 个 Plan推荐 | Plan 1: D-0+D-1+D-2基础层Plan 2: D-3功能层—— 与 Phase 2 分法类似 | ✓ |
| 1 个 Plan | D-0~D-3 全在一个 Plan 里,顶序执行,简单直接但回滚粒度较粗 | |
| 3 个 Plan | Plan 1: D-0Plan 2: D-1+D-2并行Plan 3: D-3 —— 粒度最细 | |
**User's choice:** 2 个 Plan推荐
**Notes:** 与 Phase 2 的"小修合并 + REALNAME 独立"分法保持风格一致
---
## 实时字段暴露范围
| Option | Description | Selected |
|--------|-------------|----------|
| 不暴露(推荐) | 实时字段仅写入 DB响应只返回存储字段满足所有成功标准 | ✓ |
| 暴露实时字段 | 在 AssetRealtimeStatusResponse 新增嵌套 DeviceRealtimeInfo 结构rssi / battery / ssid 等),需较大 DTO 改动 | |
**User's choice:** 不暴露(推荐)
**Notes:** 成功标准 2/4 只要求 online_status / software_version 等存储字段同步,不特别要求实时字段。实时字段暴露推迟到后续阶段按需决策。
---
## is_current DTO 同步范围
| Option | Description | Selected |
|--------|-------------|----------|
| 两处都加(推荐) | BoundCardInfoasset_dto.go+ DeviceCardBindingResponsedevice_dto.go同时新增 is_current | ✓ |
| 仅 BoundCardInfo | 只改 BoundCardInfo设备管理页绑定列表看不到当前卡标识 | |
**User's choice:** 两处都加(推荐)
**Notes:** 保持前端两个场景下的数据一致性
---
## Gateway 类型定义位置
| Option | Description | Selected |
|--------|-------------|----------|
| 放 models.go推荐 | 与现有 DeviceInfoReq / SlotInfoResp 等结构保持一致Gateway 类型集中在一个文件 | ✓ |
| 放 device.go | 跟修正文档建议,类型和方法在同一文件,但与其他 Gateway 结构不一致 | |
**User's choice:** 放 models.go推荐
**Notes:** 修正文档将类型嵌入 device.go 代码片段属于示意用法,不代表最终放置位置,遵循现有项目分离风格
---
## Agent's Discretion
- `updateDeviceFromSyncInfo` 内 is_current 更新的事务策略(先全 false 再设 true
- `last_online_time` 字符串 → time.Time 的 Parse 格式
- GORM Updates 而非 Save 的具体写法
## Deferred Ideas
- 设备实时字段rssi / battery / ssid 等)暴露到 Refresh 响应 —— 超出当前成功标准
- DeviceRealtimeInfo 独立 DTO 结构 —— 等实时字段暴露需求时再建