## ADDED Requirements ### Requirement: Exchange List Separate Asset Query Contract The exchange management list integration SHALL query `GET /api/admin/exchanges` with optional `old_asset_keyword` and `new_asset_keyword` parameters instead of the deprecated generic `identifier` parameter. #### Scenario: Query by old asset only - **GIVEN** 用户在换货管理列表的“旧资产”输入框中填写关键词 - **AND** “新资产”输入框为空 - **WHEN** 用户执行搜索 - **THEN** 请求 MUST include `old_asset_keyword` with the entered value - **AND** 请求 MUST NOT include `new_asset_keyword` - **AND** 请求 MUST NOT include `identifier` #### Scenario: Query by new asset only - **GIVEN** 用户在换货管理列表的“新资产”输入框中填写关键词 - **AND** “旧资产”输入框为空 - **WHEN** 用户执行搜索 - **THEN** 请求 MUST include `new_asset_keyword` with the entered value - **AND** 请求 MUST NOT include `old_asset_keyword` - **AND** 请求 MUST NOT include `identifier` #### Scenario: Combine old and new asset keywords - **GIVEN** 用户在“旧资产”和“新资产”输入框中均填写关键词 - **WHEN** 用户执行搜索 - **THEN** 请求 MUST include both `old_asset_keyword` and `new_asset_keyword` - **AND** 后端返回同时匹配两项条件的换货单 #### Scenario: Omit empty asset keywords - **GIVEN** “旧资产”和“新资产”输入框均为空 - **WHEN** 用户查询、刷新、切换分页或重置搜索条件 - **THEN** 请求 MUST NOT include `old_asset_keyword` - **AND** 请求 MUST NOT include `new_asset_keyword` - **AND** 请求 MUST NOT include `identifier` #### Scenario: Preserve raw asset keyword input - **GIVEN** 用户输入 ICCID、接入号、虚拟号、IMEI 或 SN 作为旧资产或新资产关键词 - **WHEN** 页面发送列表查询请求 - **THEN** 页面 MUST pass the entered text unchanged in its corresponding keyword parameter - **AND** 页面 MUST NOT convert an access number, virtual number, or other identifier into another asset identifier ### Requirement: Exchange List Separate Asset Display Contract The exchange list-item contract SHALL preserve `old_asset_type`, `old_asset_id`, `old_asset_identifier`, `new_asset_type`, `new_asset_id`, `new_asset_identifier`, `status`, and `status_name` from each `GET /api/admin/exchanges` item. #### Scenario: Parse old and new asset fields - **GIVEN** 换货列表接口返回一条换货单 - **WHEN** 前端解析该列表项 - **THEN** 前端类型 MUST support the old asset type, ID, and identifier fields independently from the new asset fields - **AND** 前端类型 MUST support `status` and `status_name` ### Requirement: Exchange List Separate Asset Columns The exchange management list SHALL display distinct columns for `旧资产类型`, `旧资产标识`, `新资产类型`, and `新资产标识`. #### Scenario: Display separate old and new IoT card assets - **GIVEN** 换货列表项的 `old_asset_type` 和 `new_asset_type` 均为 `iot_card` - **WHEN** 页面渲染换货列表行 - **THEN** 旧资产类型和新资产类型 MUST each display `物联网卡` - **AND** 旧资产标识 MUST display `old_asset_identifier` as the backend-returned ICCID - **AND** 新资产标识 MUST display `new_asset_identifier` as the backend-returned ICCID #### Scenario: Display separate old and new device assets - **GIVEN** 换货列表项的旧资产或新资产类型为 `device` - **WHEN** 页面渲染换货列表行 - **THEN** 对应资产类型 MUST display `设备` - **AND** 对应资产标识 MUST display its backend-returned device number #### Scenario: Keep old and new asset values separated - **GIVEN** 换货列表接口返回新旧资产字段 - **WHEN** 页面渲染换货列表行 - **THEN** 旧资产列 MUST only read `old_asset_type` and `old_asset_identifier` - **AND** 新资产列 MUST only read `new_asset_type` and `new_asset_identifier` - **AND** 页面 MUST NOT substitute a missing new asset value with an old asset value #### Scenario: Display unavailable new asset placeholder - **GIVEN** 换货列表项尚未关联新资产,或新资产类型或标识为空 - **WHEN** 页面渲染新资产列 - **THEN** 页面 MUST display a stable placeholder for each unavailable value #### Scenario: Display backend exchange status name - **GIVEN** 换货列表项返回 `status_name` - **WHEN** 页面渲染状态列 - **THEN** 页面 MUST display `status_name` - **AND** 当 `status_name` 缺失时页面 MUST display a stable placeholder