更新一下
This commit is contained in:
89
.scratch/ur45-exchange-asset-search/PRD.md
Normal file
89
.scratch/ur45-exchange-asset-search/PRD.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# PRD:UR#45 换货资产标识与新旧资产独立搜索
|
||||
|
||||
Status: ready-for-agent
|
||||
|
||||
---
|
||||
|
||||
## Problem Statement
|
||||
|
||||
换货单中的卡资产标识没有统一:旧资产可能保存虚拟号,新资产可能原样保存操作员输入的 ICCID、接入号或虚拟号,导致同类记录展示不一致。现有列表又只有一个同时匹配新旧资产快照的 `identifier` 参数,无法明确查“旧资产”还是“新资产”,也无法稳定通过卡的其他标识找到对应换货单。
|
||||
|
||||
## Solution
|
||||
|
||||
新建换货单时,将卡的新旧资产标识统一规范为 ICCID;设备使用稳定的设备号。换货列表用 `old_asset_keyword` 和 `new_asset_keyword` 替代通用 `identifier`,先将关键词解析为候选卡/设备 ID,再按换货单的新旧资产主键筛选。两个参数可独立使用,同时提供时按 AND 组合。
|
||||
|
||||
## User Stories
|
||||
|
||||
1. 作为运营人员,我希望换货列表分别展示旧资产和新资产,避免混淆换出和换入对象。
|
||||
2. 作为运营人员,我希望通过 ICCID、接入号或虚拟号搜索卡对应的旧资产换货记录。
|
||||
3. 作为运营人员,我希望用相同标识搜索新资产,但不会误命中旧资产。
|
||||
4. 作为运营人员,我希望同时填写新旧资产条件,以定位一条明确的换货关系。
|
||||
5. 作为维护人员,我希望新换货单保存规范化快照,历史展示不再取决于操作员当时输入了哪种标识。
|
||||
6. 作为维护人员,我希望大结果集查询不逐条反查资产,也不绕过换货单数据权限。
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### 快照规范
|
||||
|
||||
- 卡资产的 `old_asset_identifier` 和 `new_asset_identifier` 均保存已解析卡记录的完整 ICCID,不保存请求原文、接入号或虚拟号。
|
||||
- 设备资产优先保存虚拟号;虚拟号为空时依次使用 IMEI、SN,确保保存稳定的设备标识。
|
||||
- 规范化覆盖物流换货和直接换货:创建旧资产快照、直接换货的新资产快照、物流发货时的新资产快照均使用同一解析能力。
|
||||
- 请求仍可使用接口当前支持的任一资产标识定位资产,但保存快照必须取解析后的权威字段。
|
||||
- 历史换货单不回填、不改写;历史列表继续按原快照展示,新的搜索能力通过资产主键关联命中历史记录。
|
||||
|
||||
### 列表接口
|
||||
|
||||
- 复用 `GET /api/admin/exchanges`。
|
||||
- 新增可选 `old_asset_keyword` 和 `new_asset_keyword`,各自最长 100 个字符。
|
||||
- 移除新契约中的通用 `identifier`;前后端在同一维护窗口切换,不再把一个参数解释为“新资产或旧资产”。
|
||||
- 单独提供旧资产关键词时只过滤 `old_asset_type + old_asset_id`;单独提供新资产关键词时只过滤 `new_asset_type + new_asset_id`。
|
||||
- 两个关键词同时提供时按 AND 组合,并继续与状态、流程类型、创建时间和分页条件按 AND 组合。
|
||||
- 空参数不增加对应条件;无候选资产或无换货单命中时返回成功空分页,不返回 404。
|
||||
- 卡关键词对 ICCID、接入号、虚拟号做包含匹配;设备关键词对虚拟号、IMEI、SN 做包含匹配。
|
||||
- 候选资产查询必须排除软删除资产;换货单查询继续排除软删除记录并应用现有店铺数据范围。
|
||||
- 候选 ID 解析和换货单过滤使用固定次数的批量查询或数据库子查询,不允许按换货单逐行读取卡或设备。
|
||||
- `total` 与 `items` 必须使用完全相同的过滤条件,排序继续使用创建时间倒序。
|
||||
- 响应继续分别返回新旧资产类型、ID、快照标识、状态及状态名称,不改变统一响应外层结构。
|
||||
|
||||
### 校验、权限与架构
|
||||
|
||||
- 列表 Handler 对整个请求 DTO 执行校验;非法长度、分页、状态、流程类型或时间参数统一返回 HTTP 400、`code=1001`、`msg=参数验证失败`,详细原因仅写日志。
|
||||
- 代理账号只能查询其现有店铺范围内的换货单;关键词解析不得扩大最终换货单范围。
|
||||
- 无权限和不存在的换货单继续使用现有防枚举错误策略,不向客户端暴露候选资产数量或主键。
|
||||
- 快照规范属于换货写用例的一部分,应由统一资产解析/规范化能力提供,不在多个 Handler 或 Service 分支复制。
|
||||
- 列表属于读取用例,可在现有 Store 上做简单增量;若候选解析和分页组合已达到复杂查询程度,则收口到 Exchange Query,但不得为此迁移整个换货模块。
|
||||
- 数据库或候选查询失败返回脱敏的统一内部错误,不得降级为“无结果”。
|
||||
|
||||
### 前端与文档
|
||||
|
||||
- 换货列表筛选区将单一资产搜索拆为“旧资产”和“新资产”两个输入框。
|
||||
- 空值不提交;两个非空值同时提交并展示 AND 查询结果。
|
||||
- 表格分别显示旧资产类型/标识和新资产类型/标识;卡直接展示后端 ICCID,设备展示后端设备号。
|
||||
- 前端不把接入号或虚拟号转换为 ICCID,也不在本地过滤当前页。
|
||||
- 沿用列表加载、空态、失败反馈和分页交互。
|
||||
- 更新 OpenAPI 参数及描述,重新生成文档;新增 UR#45 中文总结并更新 README 索引。
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
- 写用例测试分别用 ICCID、接入号、虚拟号创建卡换货,验证新旧快照始终为数据库 ICCID。
|
||||
- 设备测试覆盖虚拟号、IMEI、SN 输入以及标识优先级。
|
||||
- 列表 HTTP 集成测试覆盖仅旧关键词、仅新关键词、两个关键词 AND、与状态/时间组合、空参数、无匹配和非法参数。
|
||||
- 覆盖卡 ICCID、接入号、虚拟号以及设备虚拟号、IMEI、SN 的候选映射。
|
||||
- 构造历史非规范快照,验证不回填但仍可通过资产主键搜索命中。
|
||||
- 代理、平台和超级管理员测试验证现有换货单数据范围不被关键词绕过。
|
||||
- 使用真实 PostgreSQL 执行代表性大结果集测试,验证查询次数固定、无逐行反查,计数和分页结果一致并满足项目性能目标。
|
||||
- 验证数据库错误返回脱敏 500,不能返回空列表掩盖故障。
|
||||
- 前端人工验收新旧字段不混列、组合搜索、清空、分页和错误状态。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 不回填或清洗历史换货快照。
|
||||
- 不新增独立搜索接口或换货关系表。
|
||||
- 不改变换货状态机、归属继承、资料迁移或完成规则。
|
||||
- 不做跨新旧资产 OR 搜索;旧通用 `identifier` 不保留为第二套长期语义。
|
||||
- 不由前端解析或规范化资产标识。
|
||||
|
||||
## Further Notes
|
||||
|
||||
- UR#45 负责“快照规范与列表检索”;资产详情前代/后代关系由 UR#86 提供,店铺继承由 UR#98 提供。
|
||||
- UR#86 应直接使用这里形成的不可变快照;历史非规范快照保持原样。
|
||||
Reference in New Issue
Block a user