All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 14m42s
- 设备资产解析外层 real_name_status:存在当前使用卡时沿用该卡状态,无任何当前卡时任一有效绑定卡已实名即视为已实名 - 手工绑定与设备导入:设备最大槽位为 1 且有效绑定唯一时,在同一事务内将该绑定初始化为当前使用卡;多卡设备不推断 - 同步 asset-device、personal-customer 主 Spec;归档变更并附存量核对清单(75 条单槽唯一待修复绑定,其中 16 条已实名)
5.5 KiB
5.5 KiB
Context
- 设备资产解析在
internal/service/asset内一次组装绑定卡、外层实名与套餐摘要;C 端资产信息 DTO 只暴露real_name_status一个外层实名信号(不含real_name_at),逐卡实名由卡列表返回。 is_current目前只在运营商设备观测、显式切卡、解绑与删设备路径写入;导入与手工绑定创建时不写,DB 默认 false。- 设备在运营商侧的识别标识为 IMEI 优先、空则用 SN,读取侧(资产信息实时状态)与观测侧(卡观测序列)口径一致。
- 生产只读核对:有有效绑定的设备 19031 台,其中 639 台无任何当前卡标识;这 639 台里 76 台存在已实名绑定卡(16 台为单槽单卡,其余为多卡设备)。
- 既有约束:自动化测试当前为 N/A(用户决策);生产写入由维护者按生产运行说明执行,Agent 只做只读诊断。
Goals / Non-Goals
Goals:
- 让「设备没有任何当前卡标识」这一分支不再把已实名设备展示为未实名。
- 让单槽单卡设备在绑定后即具备当前卡标识,消除「当前卡」展示为空的产生条件。
- 给存量同类数据一个可复核、可回滚的核对与修复口径。
Non-Goals:
- 不改变存在当前卡标识时的判定结果。
- 不改变管理端设备列表既有的「任一有效绑定卡已实名」筛选,以及设备激活状态判定。
- 不为多卡设备推断当前卡,不改变运营商观测/切卡对
is_current的写入职责。 - 不处理运营商侧设备登记(如 Gateway 返回设备号无效)的修复。
- 不引入 Schema 变更、迁移、一次性常驻命令或自动化测试。
Decisions
1. 回退判定放在读取侧,不改写业务事实
无当前卡时,外层实名按有效绑定卡的实名状态取或(任一已实名即已实名),实现位置为设备资产解析中的外层实名判定。
- 理由:读取侧回退只影响展示,不把「哪张卡在用」变成猜测事实;多卡设备无当前卡写侧无法推断,回填会污染
is_current语义。 - 备选:在所有情况下都改为「任一有效绑定卡已实名」(否决,等于回退既有当前卡语义);在读取时按最大槽位推断当前卡(否决,会让
is_current出现第二套判定来源)。
2. 保留「当前卡优先」分支,仅补分支缺口
存在 is_current=true 的有效绑定时沿用该卡实名状态;仅在一条当前卡标识都没有时进入回退。如此本 change 不改变有当前卡设备的既有返回。
3. 绑定创建时初始化单槽单卡的当前卡标识
判据:设备最大槽位为 1,且绑定创建后该设备的有效绑定唯一。此时设备只有唯一的可能当前卡,标记为当前使用卡是事实而非猜测。写入与绑定创建放在同一事务,保证绑定与当前卡标识一致可见;导入与手工绑定两条创建路径都要覆盖。
- 理由:多卡设备的当前卡必须来自运营商观测或显式切卡,绑定时不猜。
- 备选:绑定后异步触发一次设备观测(否决,依赖外部调用且失败时仍留空)。
4. 存量数据走受控人工修复,不写一次性代码
只读核对口径(识别待修复绑定):
SELECT d.id AS device_id, b.id AS binding_id, b.iot_card_id
FROM tb_device_sim_binding b
JOIN tb_device d ON d.id = b.device_id AND d.deleted_at IS NULL
WHERE b.bind_status = 1
AND d.max_sim_slots = 1
AND NOT EXISTS (SELECT 1 FROM tb_device_sim_binding x
WHERE x.device_id = b.device_id AND x.bind_status = 1 AND x.is_current)
AND (SELECT count(*) FROM tb_device_sim_binding y
WHERE y.device_id = b.device_id AND y.bind_status = 1) = 1;
受控修复:仅对上述结果集内的绑定置 is_current = true,同一设备只允许一条;执行前留存核对结果,执行后抽样比对设备卡列表与资产信息。
- 理由:生产写操作由维护者执行;一次性命令会长期留在仓库成为隐性维护面。
- 备选:新增数据修复命令或迁移(否决,超出必要范围且规则与绑定创建规则重复)。
Risks / Trade-offs
- [无当前卡集合里包含「当前卡标识因观测缺失而丢失」的设备,回退可能把实际在用卡未实名的设备显示为已实名] → 以绑定卡本地事实为准,卡列表仍逐卡返回真实状态;上游设备登记类问题另行在运维侧处理,不在本 change。
- [绑定即置当前卡可能让设备观测的期望值提前满足] → 判据限定最大槽位为 1 且有效绑定唯一,此时可被切换的目标只有同一张卡;多卡设备不写入。
- [存量修复误伤多卡或重复当前卡] → 核对口径限定单槽且唯一有效绑定,修复语句限定
bind_status = 1并保证同一设备至多一条is_current;先只读核对,再小批执行。 - [C 端展示口径变化无自动化测试覆盖] → 按用户既有决策不新增自动化测试,改为对案例设备(19090)与抽样设备做发布后实接口核对。
Migration Plan
- 代码发布:无 Schema 变更,随常规二进制发布生效;展示口径回退只需回滚二进制,无数据残留。
- 存量修复:先在只读环境按核对口径确认结果集,再由维护者按生产运行说明执行修复;不随发布自动执行。
- 发布后核对:以案例设备
90001595626与抽样多卡设备比对资产信息外层实名、卡列表当前卡标识。