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

@@ -714,3 +714,38 @@ IotCard Service SHALL 提供 Gateway API 的代理方法,封装权限检查和
- **WHEN** 调用任意 Gateway 代理方法且 ICCID 对应的卡不存在或用户无权限
- **THEN** 返回 `CodeNotFound` 错误
- **AND** 错误信息为 "卡不存在或无权限访问"
---
### Requirement: IoT 卡虚拟号字段
系统 SHALL 在 `tb_iot_card` 表新增 `virtual_no` 字段,与设备的虚拟号概念对等,供客服和客户通过统一虚拟号查找资产。
**字段定义**:
- 字段名:`virtual_no`VARCHAR(50),可空)
- 全局唯一索引:`CREATE UNIQUE INDEX idx_iot_card_virtual_no ON tb_iot_card (virtual_no) WHERE deleted_at IS NULL`
- 老数据:`virtual_no` 为 NULL已有卡不强制要求有虚拟号
- 允许手动修改
**唯一性规则**:
- 在所有未软删除的卡中唯一部分索引deleted_at IS NULL
- 导入时与数据库现存数据重复则整批失败,响应中包含冲突的具体 virtual_no 列表
**虚拟号的使用场景**:
- resolve 接口:支持通过 virtual_no 查找卡
- 客服工单:客服将虚拟号告知客户,客户通过虚拟号自助查询
#### Scenario: 为卡设置唯一虚拟号
- **WHEN** 管理员为 ICCID 为 "898601234..." 的卡设置 virtual_no = "CARD-001"
- **THEN** 系统保存成功,`idx_iot_card_virtual_no` 确保全局唯一
#### Scenario: 导入批次中有重复虚拟号
- **WHEN** ICCID 导入批次中,有 1 条记录的 virtual_no 与数据库现存卡的 virtual_no 重复
- **THEN** 系统拒绝整批导入,响应中返回冲突的 virtual_no 及所属行号
#### Scenario: virtual_no 为空的老卡
- **WHEN** 系统中有历史导入的卡,没有 virtual_no
- **THEN** 这些卡的 virtual_no = NULL不影响唯一索引部分索引跳过 NULL 值)