Files
junhong_cmp_fiber/.scratch/ur62-h5-realname-order/PRD.md
2026-07-21 15:26:07 +09:00

105 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PRDUR#62 H5 购买与实名顺序配置
Status: ready-for-agent
---
## Problem Statement
卡和设备已经保存 `realname_policy`,也已有单资产修改接口,但 C 端充值、购买、实名入口分别维护局部判断,接口仍只返回原始策略,无法稳定表达“运营商实名能力优先于资产顺序策略”。后台也缺少卡和设备的批量配置能力。
设备场景还存在两个容易混淆的概念:每张卡是否需要实名由其运营商 `realname_link_type` 决定;设备的 `realname_policy` 只决定购买和实名的先后顺序。本期设备数据前提是所有有效绑定卡都需要实名,不提前设计设备内混有无需实名卡的流程。
## Solution
建立统一的有效实名策略解析和购买资格规则。独立卡使用卡策略;设备以及从设备入口访问的卡使用设备策略。对每张卡,`realname_link_type=none` 表示无需实名,`template/gateway` 表示需要实名。独立卡据此计算有效策略;设备本期仅允许 `before_order/after_order`,并按全部有效绑定卡的实名结果决定购买资格。
保留现有单资产修改接口新增卡和设备批量配置接口。C 端初始化直接返回有效策略、是否需要实名和实际实名状态,前端只编排页面,不复制后端判断。
## User Stories
1. 作为 C 端客户,我希望无需实名的独立卡直接进入购买流程。
2. 作为 C 端客户,我希望“先实名后购买”的独立卡在未实名时先完成实名。
3. 作为设备客户,我希望设备配置为先实名时,全部有效绑定卡完成实名后才能购买。
4. 作为设备客户,我希望设备配置为先购买时,可以完成购买后再逐张处理未实名卡。
5. 作为运营人员,我希望在卡或设备列表一次修改最多 500 个资产的实名顺序,并保证全成全败。
6. 作为运营人员,我希望设备下卡的页面明确提示 H5 顺序由设备策略控制。
7. 作为审计人员,我希望单条和批量变更都留下统一审计记录。
## Implementation Decisions
### 领域语义
- 卡的 `realname_link_type` 始终决定该卡是否需要实名:`none` 为无需实名,`template/gateway` 为需要实名。
- `realname_policy` 只描述购买与实名顺序:`none``before_order``after_order`;默认值继续为 `after_order`
- 独立卡使用卡自身 `realname_policy`。若 `realname_link_type=none`,有效策略固定为 `none`;若为 `template/gateway` 而卡策略为 `none`,这是冲突数据,初始化和购买均明确报错,不得静默放行。
- 设备以及从设备入口解析出的卡使用设备 `realname_policy`,绑定卡自身策略不参与设备 H5 顺序。
- 本期确认设备的全部有效绑定卡都需要实名,因此设备策略只允许 `before_order``after_order`;设备配置 `none` 属于非法配置。
- 本期仍按每张卡的 `realname_link_type` 生成具体实名入口,但不设计设备内出现 `realname_link_type=none` 卡时的资格、展示和批量交互;未来出现该业务后另行扩展。
- 设备 `before_order` 的购买资格是所有有效绑定、未软删除的卡均 `real_name_status=1`;无绑定卡或任一卡未实名都不允许购买。
- 设备 `after_order` 允许先购买;购买完成后返回全部尚未实名的有效绑定卡,前端逐张引导实名。
- UR#53 的设备 `real_name_status` 是列表筛选投影,语义为“任一有效绑定卡已实名”;不得用该快照代替本需求的“全部有效绑定卡已实名”购买资格判断。
- 卡的 `realname_link_type`、实名状态及有效绑定关系由数据同步公共 DDD 提供;本需求不得在 C 端 Handler 复制第二套状态规则。
### API 契约
- 保留 `PATCH /api/admin/assets/{identifier}/realname-mode`,请求为 `{ "realname_policy": "none|before_order|after_order" }`
- 新增 `POST /api/admin/iot-cards/batch-update-realname-policy`
- 新增 `POST /api/admin/devices/batch-update-realname-policy`
- 两个批量接口统一请求:`asset_ids` 为去重后的正整数数组1500 项;`realname_policy` 使用上述枚举。
- 卡批量配置允许三个值,但每张卡都执行运营商能力冲突校验;设备批量配置只允许 `before_order/after_order`
- 任一资产不存在、软删除、越权、类型不符或策略冲突时整批失败,不更新任何资产;错误不得泄露越权资源是否存在。
- 单条和批量接口复用同一 Application 校验规则,不能出现单条可写、批量不可写或反向不一致。
- C 端 `GET /api/c/v1/asset/info` 增加 `effective_realname_policy``realname_required`,继续返回实际 `real_name_status`;原 `realname_policy` 在兼容期保留为配置原值,不再供新前端决定流程。
- 设备响应还应返回 `pending_realname_cards`,仅包含当前客户有权操作且尚未实名的有效绑定卡必要信息;不得返回身份证等敏感信息。
- `realname_required` 对独立卡按卡运营商能力返回;对设备本期固定为 `true`,但仍必须经过设备绑定完整性校验。
- 充值校验、创建充值、创建套餐订单和实名链接入口都调用统一有效策略/资格用例,禁止继续散落比较 `RealnamePolicy`
- 参数解析和完整 DTO 校验失败统一返回参数错误;所有枚举 description 从常量原文同步。
### 事务、权限与审计
- 批量写操作使用 Application 事务脚本:一次批量加载权限范围内资产及必要运营商能力,完成全量校验后批量更新。
- 不逐资产查询运营商、绑定或权限,最多 500 项仍必须批量读取。
- 单条和批量成功后写 Audit Event批量事件记录目标类型、数量、目标策略和请求 ID不在日志中写客户实名敏感数据。
- 代理和平台账号继续使用现有资产数据范围;批量更新不得绕过 GORM Callback 和业务权限检查。
- 重复设置相同策略按幂等成功处理,不制造多次业务副作用;审计中可标记实际变更数量。
### 前端
- 卡、设备列表分别增加批量“修改实名顺序”,显示已选择数量,最多 500 项。
- 卡可选无需实名、先实名后购买、先购买后实名;设备只展示后两项。
- 修改设备下卡策略时提示“实际 H5 流程由设备策略决定”。
- C 端只读取 `effective_realname_policy``realname_required` 和后端返回的待实名卡,不按资产类型或运营商类型自行覆盖。
- `before_order` 未满足时引导实名;`after_order` 在购买完成后引导未实名卡;冲突数据展示后端中文错误并停止流程。
### 发布与依赖
- 本需求依赖数据同步公共 DDD 提供统一卡事实和有效绑定读取边界;公共能力未落地前不得在旧 C 端 Handler 增加临时分支。
- 发布前扫描独立卡 `realname_link_type!=none && realname_policy=none` 以及设备 `realname_policy=none` 的冲突数据,形成修复清单;运行时仍保留拒绝保护。
- API 和对应 C 端、后台前端同一维护窗口发布;旧 `realname_policy` 响应字段只做兼容,不长期承载流程语义。
## Testing Decisions
- 领域测试覆盖独立卡的 `none/template/gateway × none/before_order/after_order × 实名0/1` 组合。
- 设备测试覆盖无绑定卡、单卡、多卡、全部已实名、部分实名、全部未实名、无效绑定和软删除卡。
- 明确验证设备资格使用“全部有效卡已实名”,而 UR#53 设备列表快照仍是“任一有效卡已实名”。
- 批量接口覆盖 1、500、501 项,重复 ID、零 ID、不存在、越权、软删除、策略冲突和整批回滚。
- HTTP 集成测试使用真实开发 PostgreSQL、Redis、JWT 和进程内 Fiber App实名 Gateway 使用测试 Adapter不调用真实上游。
- 回归充值校验、创建充值、套餐购买、实名链接和设备逐卡实名,证明所有入口使用同一策略。
- 验证相同策略重复提交幂等、审计实际变更数量正确,且批量查询无 N+1。
- 前端验收三种独立卡流程、两种设备流程、批量交互、冲突错误和购买后逐卡引导。
## Out of Scope
- 不设计设备内混有无需实名卡时的有效策略和 UI。
- 不修改 `realname_link_type` 的配置入口或实名链接生成协议。
- 不改变 UR#53 的设备实名筛选投影语义。
- 不新增全局实名策略默认配置。
- 不实现数据同步公共 DDD、运营商回调或实名轮询本身。
## Further Notes
- 当前代码已经具备字段、默认值、单条接口和部分前置校验,但这些属于迁移输入;目标是统一资格用例,而不是继续复制条件。
- `realname_link_type` 决定“这张卡是否需要实名”,`realname_policy` 决定“什么时候实名”,两者不得互相替代。