# 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** 创建新设备(通过导入或 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 到原有查询逻辑