提案
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 56s

This commit is contained in:
Break
2026-06-04 09:39:20 +08:00
parent 5089a71764
commit 27fba9160c
14 changed files with 1341 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
## MODIFIED Requirements
### Requirement: 查询资产跨代历史订单(含前代)
`include_previous=true` 时,系统 SHALL 通过换货链追溯前代资产,返回前代订单,并在响应中区分世代来源。
**追溯逻辑**
1. 通过 `ExchangeOrder.new_asset_id` 逆向查找当前资产的换货来源
2. 得到前代的 `old_asset_identifier`,查询该标识符的订单
3. 递归追溯,最多向前 10 代(安全上限)
4. 追溯范围 MUST 同时覆盖 `flow_type=shipping``flow_type=direct` 的已完成换货单
5. 追溯 MUST 仅使用 `status=4` 的已完成换货单,禁止把发货中、取消或半成品记录纳入链路
6. 历史记录若 `flow_type` 为空或缺失,系统 MUST 按 `shipping` 兼容处理
**响应结构AssetOrdersResponse**
```json
{
"current_generation": {
"generation": 2,
"identifier": "DEV-001",
"asset_type": "device",
"total": 5,
"page": 1,
"page_size": 20,
"items": [ ...... ]
},
"previous_generations": [
{
"generation": 1,
"identifier": "DEV-OLD-001",
"asset_type": "device",
"exchange_no": "EXC20260101XXXXXX",
"exchanged_at": "2026-01-01T00:00:00Z",
"total": 3,
"items": [ ...20... ]
}
],
"truncated": false
}
```
`previous_generations[].exchanged_at` MUST 优先取换货单 `completed_at`,不得在 `completed_at` 存在时直接将 `updated_at` 视为真实换货完成时间。
若历史单据尚无 `completed_at`,系统 MUST 采用 `updated_at` 兼容回退策略;新完成单据 MUST 优先使用 `completed_at`
#### Scenario: 查询 direct 换货后的全代际订单
- **WHEN** 管理员请求 `GET /api/admin/assets/DEV-NEW-001/orders?include_previous=true`,且当前资产来自一次 `flow_type=direct` 的已完成换货
- **THEN** `previous_generations` MUST 返回来源旧资产的订单链
- **AND** `exchanged_at` MUST 返回该换货单的 `completed_at`
#### Scenario: 查询 shipping 换货后的全代际订单
- **WHEN** 管理员请求 `GET /api/admin/assets/DEV-001/orders?include_previous=true`DEV-001 来自一次 `flow_type=shipping` 的已完成换货
- **THEN** `current_generation` 包含 DEV-001 本代的订单
- **AND** `previous_generations[0]` 包含来源旧资产的订单,并附带换货单号和真实完成时间
#### Scenario: 未完成换货单不进入追溯链
- **WHEN** 当前资产只存在 `status=3` 的发货待确认换货单来源记录
- **THEN** `include_previous=true` MUST NOT 将该换货单作为前代来源
#### Scenario: 历史完成单据回退完成时间
- **WHEN** 前代来源换货单 `status=4``completed_at` 为空
- **THEN** `previous_generations[].exchanged_at` MUST 使用该换货单 `updated_at` 兼容回退
#### Scenario: 资产本身就是第一代(无前代)
- **WHEN** 管理员请求带 `include_previous=true`,但该资产从未经过换货
- **THEN** `previous_generations` 为空数组 `[]`
- **AND** `current_generation` 正常返回本代订单
#### Scenario: 换货链超过追溯上限
- **WHEN** 换货链深度超过 10 代
- **THEN** 追溯在第 10 代截断,`truncated=true`
- **AND** 已追溯到的前代数据正常返回
#### Scenario: 前代订单分页
- **WHEN** 请求带 `include_previous=true`
- **THEN** 分页参数page/page_size只对 `current_generation` 的订单生效
- **AND** 前代订单每代最多返回 20 条(不支持前代内分页)
#### Scenario: 无 include_previous 时响应不含前代字段
- **WHEN** 管理员请求不带 `include_previous=true`(或传 false
- **THEN** 响应结构中 `previous_generations` 字段为 null 或不返回,节省带宽