## ADDED 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** 创建新设备（通过导入或 API），VirtualNo 非空
- **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** 系统需要根据 identifier（ICCID 或 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 到原有查询逻辑
