Files
junhong_cmp_fiber/openspec/specs/asset-identifier-registry/spec.md
huang 80c6f6c756
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m21s
feat: 资产标识符标准化、资产历史订单查询及导入虚拟号强制验证
主要变更:
- 新增 AssetIdentifier 模型及 Store,统一管理资产标识符(ICCID/IMEI/SN 等)
- 新增迁移:asset_identifier 表、order 表新增 asset_identifier 字段、iot_card.virtual_no NOT NULL 约束
- 资产 Handler/Service/Route 全面重构,支持标识符路由查询与解析
- 新增资产历史订单查询接口,支持跨设备/卡/钱包维度的订单聚合
- 设备与物联卡导入任务强制校验虚拟号,缺失时直接拒绝
- Excel 工具函数优化,前端导入指引文档同步更新
- 归档三个 OpenSpec 提案:asset-identifier-standardization、asset-historical-orders、import-mandatory-virtual-no
- 更新 OpenAPI 文档及相关 DTO

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-07 17:39:36 +08:00

53 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Capability: 全局资产标识符注册表
## Purpose
维护一张全局唯一的资产标识符注册表(`tb_asset_identifier`),在数据库层保证 IoT 卡的 ICCID/VirtualNo 与设备的 VirtualNo 跨两张表不重复,消除并发写入竞态风险,同时提供高性能的标识符→资产 ID 精确查找能力。
## Requirements
### Requirement: 全局资产标识符注册表
系统 SHALL 维护一张全局唯一的资产标识符注册表(`tb_asset_identifier`),在数据库层保证 IoT 卡的 ICCID/VirtualNo 与设备的 VirtualNo 跨两张表不重复,消除并发写入竞态风险。
注册表仅存储**全局唯一标识符**ICCID、VirtualNo不存储 IMEI/SN/MSISDN 等非唯一标识符。
**表字段**
- `id`:自增主键
- `identifier`标识符值VARCHAR(100)UNIQUE 约束)
- `asset_type`:资产类型(`iot_card``device`
- `asset_id`:对应资产的主键 ID
- `created_at`:写入时间
#### Scenario: 创建设备时注册 VirtualNo
- **WHEN** 创建新设备(通过导入或 APIVirtualNo 非空
- **THEN** 系统在同一事务内向 `tb_asset_identifier` 写入一条记录identifier=VirtualNo, asset_type=device, asset_id=新设备ID
- **THEN** 若 VirtualNo 已在注册表中存在,事务回滚,返回错误"虚拟号已被占用"
#### Scenario: 创建 IoT 卡时注册 ICCID
- **WHEN** 创建新 IoT 卡通过导入ICCID 非空
- **THEN** 系统在同一事务内向注册表写入identifier=ICCID, asset_type=iot_card, asset_id=新卡ID
- **THEN** 若 ICCID 已在注册表中存在,事务回滚,返回错误"ICCID 已被占用"
#### Scenario: 创建 IoT 卡时注册 VirtualNo如有
- **WHEN** 创建新 IoT 卡时 VirtualNo 非空
- **THEN** 系统额外向注册表写入identifier=VirtualNo, asset_type=iot_card, asset_id=新卡ID
- **THEN** 若 VirtualNo 已被其他设备或卡占用,事务回滚,返回错误"虚拟号已被占用"
#### Scenario: 并发写入同一标识符
- **WHEN** 两个并发请求同时尝试注册相同的 VirtualNo如 "CARD-001"
- **THEN** 数据库 UNIQUE 约束保证只有一个写入成功;另一个收到唯一约束冲突错误,事务回滚,返回错误"虚拟号已被占用"
#### Scenario: 软删除资产时清理注册表
- **WHEN** 软删除设备或 IoT 卡
- **THEN** 系统在同一事务内删除 `tb_asset_identifier` 中对应的记录(所有 asset_id 匹配的行),允许标识符被后续资产复用
#### Scenario: 通过标识符精确查找资产
- **WHEN** 系统需要根据 identifierICCID 或 VirtualNo定位资产
- **THEN** 系统查询 `SELECT * FROM tb_asset_identifier WHERE identifier = ?`,一次查询得到 asset_type 和 asset_id
- **THEN** 再按 asset_type 查对应表(`tb_device``tb_iot_card`)取完整记录
#### Scenario: 查询不存在的标识符
- **WHEN** 查询注册表中不存在的 identifier
- **THEN** 返回空结果not found调用方可 fallback 到原有查询逻辑