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

8.8 KiB
Raw Blame History

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 只描述购买与实名顺序:nonebefore_orderafter_order;默认值继续为 after_order
  • 独立卡使用卡自身 realname_policy。若 realname_link_type=none,有效策略固定为 none;若为 template/gateway 而卡策略为 none,这是冲突数据,初始化和购买均明确报错,不得静默放行。
  • 设备以及从设备入口解析出的卡使用设备 realname_policy,绑定卡自身策略不参与设备 H5 顺序。
  • 本期确认设备的全部有效绑定卡都需要实名,因此设备策略只允许 before_orderafter_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_policyrealname_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_policyrealname_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 决定“什么时候实名”,两者不得互相替代。