# exchange-admin-management Specification

## Purpose

提供后台换货单管理能力，涵盖换货单的发起、列表查询、详情查看、发货、确认完成、取消及旧资产转新等完整生命周期管理。

## Requirements

### Requirement: H1 发起换货单

系统 SHALL 提供 `POST /api/admin/exchanges`（需后台认证 `Auth=true`），用于发起换货单。

请求体 MUST 包含：`old_asset_type`、`old_identifier`、`exchange_reason`，可选 `remark`。

系统 MUST 校验：
- 旧资产存在且当前用户有权限
- 同一资产不存在进行中的换货单（`status IN (1,2,3)`）

成功响应 SHALL 返回新建换货单信息（含 `id`、`exchange_no`、`status=1`）。

错误响应 MUST 至少包含：参数错误、资产不存在或无权限、存在进行中换货单。

#### Scenario: 资产已有进行中换货单
- **WHEN** 后台为同一资产重复发起换货
- **THEN** 系统 MUST 拒绝创建并返回"存在进行中的换货单"

---

### Requirement: H2 换货单列表

系统 SHALL 提供 `GET /api/admin/exchanges`（`Auth=true`），支持分页与条件查询。

查询条件 SHOULD 支持：`status`、`identifier`（资产标识搜索）、`created_at_start`、`created_at_end`、分页参数。

响应 SHALL 返回列表与分页元数据。

#### Scenario: 按状态查询待发货单
- **WHEN** 运营查询 `status=2`
- **THEN** 系统返回所有待发货换货单并按创建时间倒序

---

### Requirement: H3 换货单详情

系统 SHALL 提供 `GET /api/admin/exchanges/:id`（`Auth=true`）查询换货单详情。

响应 MUST 返回旧/新资产信息、收货信息、物流信息、迁移状态信息。

错误响应 MUST 至少包含：换货单不存在或无权限。

#### Scenario: 查询不存在换货单
- **WHEN** 查询不存在的换货单 ID
- **THEN** 系统 MUST 返回"资源不存在或无权限"

---

### Requirement: H4 发货

系统 SHALL 提供 `POST /api/admin/exchanges/:id/ship`（`Auth=true`）。

请求体 MUST 包含：`express_company`、`express_no`、`new_identifier`、`migrate_data`。

系统 MUST 校验：
- 当前状态必须为 `2`
- 新旧资产类型必须一致（卡换卡/设备换设备）
- 新资产必须 `asset_status=1`（在库）

成功后 SHALL 更新新资产信息、物流信息并将状态改为 `3`。

错误响应 MUST 至少包含：非法状态、资产类型不匹配、新资产非在库、资产不存在或无权限。

#### Scenario: 新资产类型不一致
- **WHEN** 旧资产为 iot_card 且新资产为 device
- **THEN** 系统 MUST 拒绝发货并返回"换货资产类型必须一致"

---

### Requirement: H5 确认完成

系统 SHALL 提供 `POST /api/admin/exchanges/:id/complete`（`Auth=true`）。

系统 MUST 校验当前状态为 `3`。当 `migrate_data=true` 时，系统 MUST 执行全量迁移事务（见 `exchange-data-migration` 能力）。

成功后 SHALL：
- `migration_completed=true`（若执行迁移）
- 换货单状态更新为 `4`

错误响应 MUST 至少包含：非法状态、迁移失败、换货单不存在或无权限。

#### Scenario: 需要迁移并完成
- **WHEN** 状态为 `3` 且 `migrate_data=true`
- **THEN** 系统 MUST 在事务成功后将状态变为 `4` 并记录迁移结果

---

### Requirement: H6 取消换货

系统 SHALL 提供 `POST /api/admin/exchanges/:id/cancel`（`Auth=true`）。

系统 MUST 仅允许在 `status IN (1,2)` 时取消，成功后状态更新为 `5`。

系统 MUST 禁止已发货单取消（`status=3`）。

#### Scenario: 已发货单取消失败
- **WHEN** 换货单状态为 `3` 发起取消
- **THEN** 系统 MUST 返回状态非法错误

---

### Requirement: H7 旧资产转新

系统 SHALL 提供 `POST /api/admin/exchanges/:id/renew`（`Auth=true`）。

系统 MUST 校验旧资产当前 `asset_status=3`（已换货），并执行：
- `generation + 1`
- `asset_status -> 1`
- 清除累计充值/首充相关状态
- 清除个人客户绑定
- 创建新空钱包

系统 MUST 保留历史数据，不执行历史删除。

错误响应 MUST 至少包含：资产状态不满足转新条件、换货单不存在或无权限。

#### Scenario: 旧资产未处于已换货状态
- **WHEN** 旧资产 `asset_status != 3` 发起转新
- **THEN** 系统 MUST 拒绝并返回"资产当前状态不允许转新"
