feat: 新增数据库迁移,重命名 device_no 为 virtual_no,新增 iot_card.virtual_no 和 package.virtual_ratio 字段
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-14 18:27:28 +08:00
parent b5147d1acb
commit b9c3875c08
77 changed files with 5832 additions and 2393 deletions

View File

@@ -8,7 +8,7 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
系统 SHALL 提供设备列表查询功能,支持多维度筛选和分页。
**查询条件**:
- `device_no`(可选): 设备号,支持模糊匹配
- `virtual_no`(可选): 设备虚拟号,支持模糊匹配(原 `device_no` 字段,已全量改名)
- `device_name`(可选): 设备名称,支持模糊匹配
- `status`(可选): 设备状态,枚举值 1-在库 | 2-已分销 | 3-已激活 | 4-已停用
- `shop_id`(可选): 店铺 IDNULL 表示平台库存
@@ -30,7 +30,7 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
**响应字段**:
- `id`: 设备 ID
- `device_no`: 设备
- `virtual_no`: 设备虚拟号(原 `device_no`,已改名)
- `device_name`: 设备名称
- `device_model`: 设备型号
- `device_type`: 设备类型
@@ -51,10 +51,10 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
- **WHEN** 平台管理员查询设备列表,不带任何筛选条件
- **THEN** 系统返回所有设备,按创建时间倒序排列
#### Scenario: 按设备号模糊查询
#### Scenario: 按虚拟号模糊查询
- **WHEN** 管理员输入 device_no = "GPS"
- **THEN** 系统返回设备号包含 "GPS" 的所有设备
- **WHEN** 管理员输入 virtual_no = "GPS"
- **THEN** 系统返回虚拟号包含 "GPS" 的所有设备
#### Scenario: 按状态筛选设备
@@ -80,7 +80,7 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
**API 端点**: `GET /api/admin/devices/:id`
**响应字段**:
- 包含设备的所有基本字段
- 包含设备的所有基本字段(含 `virtual_no`,不再有 `device_no`
- `shop_name`: 店铺名称(如果有)
**数据权限**:
@@ -90,7 +90,7 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
#### Scenario: 查询设备详情成功
- **WHEN** 管理员查询设备详情ID=1
- **THEN** 系统返回该设备的完整基本信息
- **THEN** 系统返回该设备的完整基本信息,响应中含 `virtual_no` 字段,不含 `device_no`
#### Scenario: 查询不存在的设备
@@ -323,3 +323,36 @@ TBD - created by archiving change add-device-management. Update Purpose after ar
- **WHEN** 代理(店铺 ID=10尝试回收非直属下级的设备
- **THEN** 系统返回错误,提示"只能回收直属下级店铺的设备"
---
### Requirement: device_no 全量改名为 virtual_no
系统 SHALL 将 `tb_device` 表和 `tb_personal_customer_device` 表中的 `device_no` 字段全量改名为 `virtual_no`,确保系统中不再有 `device_no` 的存在。
**数据库变更**:
```sql
ALTER TABLE tb_device RENAME COLUMN device_no TO virtual_no;
ALTER TABLE tb_personal_customer_device RENAME COLUMN device_no TO virtual_no;
```
**代码影响范围**:
- `internal/model/device.go``DeviceNo``VirtualNo`column tag 更新
- `internal/model/personal_customer_device.go``DeviceNo``VirtualNo`column tag 更新
- `internal/model/dto/device_dto.go``DeviceResponse.DeviceNo``VirtualNo`JSON tag 更新为 `"virtual_no"`
- `internal/store/postgres/device_store.go``GetByIdentifier` 查询条件中 `device_no``virtual_no`
- `internal/store/postgres/personal_customer_device_store.go`:所有 `device_no` 引用更新
- 所有 Handler、Service 中引用 `DeviceNo` 字段的代码全量替换
**设备导入模板**:
- 导入 Excel 模板中的列头从 `device_no` 更新为 `virtual_no`
#### Scenario: 改名后查询设备
- **WHEN** 改名迁移完成后,调用 `GetByIdentifier("GPS-001")`
- **THEN** 系统在 `WHERE virtual_no = ? OR imei = ? OR sn = ?` 中正确匹配,与改名前行为一致
#### Scenario: 响应中字段名已更新
- **WHEN** 前端调用设备列表或详情接口
- **THEN** 响应 JSON 中 key 为 `virtual_no`,不再有 `device_no`