5.1 KiB
5.1 KiB
Context
当前设备导入链路分为两段:
pkg/utils/excel.go负责按固定列读取设备导入 Excel。internal/task/device_import.go负责校验卡并创建tb_device_sim_binding记录。
现状问题在于解析层只保留“非空 ICCID 列表”,没有保留“这个 ICCID 原来来自第几个卡槽列”。任务层随后按数组顺序写入 slot_position = i + 1,使得源文件中的空槽位被压缩。这个问题不涉及新接口,也不需要调整数据库结构,但会跨越解析层与任务执行层,适合先通过设计文档把数据语义钉死。
约束条件:
- 必须遵守现有
Handler → Service → Store → Model分层,不把槽位推断逻辑散落到多处。 - 不新增表结构,不引入新依赖。
- 设备导入仍走 Asynq 异步任务,保持当前事务边界和幂等行为。
- 文档、日志、错误消息保持中文。
Goals / Non-Goals
Goals:
- 保留 Excel
卡1~卡4的原始槽位信息,避免前置空槽被压缩。 - 让导入创建的
slot_position与 Excel 列号严格一致。 - 对
max_sim_slots之外的已填写 ICCID 给出明确失败规则。 - 让后续查询设备绑定关系、切卡和运维判断都基于正确槽位数据。
Non-Goals:
- 不新增或修改导入 API。
- 不修复历史上已经错误导入的数据。
- 不改变设备导入任务的权限、批次、实名策略等既有能力。
- 不引入自动化测试要求,本次仅定义实现任务和手工验收路径。
Decisions
决策1:在解析结果中保留“槽位 + ICCID”映射,而不是仅保留 ICCID 列表
选择:
设备导入解析结构需要显式表达每张卡来自哪个槽位,例如保留 slot_position 与 iccid 的成对关系,或者使用等价的固定槽位结构。
理由:
- 只有解析层知道 ICCID 来自哪一列,到了任务层再推断已经丢失上下文。
- 把槽位语义前置到解析结果,可以让任务层只负责校验和落库,职责更清晰。
备选方案:
- 在任务层根据 ICCID 顺序反推槽位:不可行,前置空槽信息已丢失。
- 用占位空字符串继续传
[]string:可读性差,容易在后续处理中再次被压缩或忽略。
决策2:绑定记录的 slot_position 直接使用源列位,不再使用连续下标
选择:
创建设备卡绑定时,slot_position 必须直接使用解析出的槽位编号,而不是 i + 1。
理由:
tb_device_sim_binding.slot_position本来就是槽位语义字段,应该存真实槽位。- 这样可以保持导入、查询、切卡、展示四个环节的语义一致。
备选方案:
- 继续写连续下标并在展示层修正:会污染底层数据,后续所有依赖槽位的逻辑都要补丁式兼容,不可接受。
决策3:填写超过 max_sim_slots 的 ICCID 时整行失败
选择:
如果 Excel 某行声明 max_sim_slots=2,却填写了 卡3 或 卡4,该行导入失败,并给出明确失败原因。
理由:
- 超出设备最大槽位的绑定关系本身就是无效数据,不能静默忽略。
- 失败比“部分导入 + 隐式丢弃”更容易让运营发现模板问题。
备选方案:
- 静默忽略越界槽位:会造成运营以为导入成功,但设备绑定不完整。
- 自动上调
max_sim_slots:篡改源数据含义,不符合设备真实硬件能力。
决策4:沿用现有事务边界,不扩大导入任务架构
选择: 仍在当前单行事务中完成设备创建、资产标识注册、卡绑定创建、卡快照更新和钱包创建,只替换槽位数据来源。
理由:
- 问题根因是数据语义错误,不是事务模型错误。
- 保持现有事务边界可以减少改动范围和回归风险。
Risks / Trade-offs
-
[风险] 解析结构变更会波及设备导入任务中遍历 ICCID 的逻辑 → Mitigation:只在设备导入专用结构中调整,不影响卡导入等其他解析路径。
-
[风险] 历史错误导入的数据仍然存在,修复后新旧数据表现不一致 → Mitigation:在提案中明确本次仅修复“后续导入行为”,历史数据如需修复需单独立项。
-
[风险] 运营模板可能继续填写越界槽位,修复后失败数会上升 → Mitigation:在失败原因中明确指出“填写槽位超出最大SIM槽数”,并更新导入使用说明。
Migration Plan
- 先更新
device-import规格,明确“列位即槽位”。 - 调整设备导入解析结构与任务执行逻辑。
- 使用手工构造的 Excel 样例做导入验收,覆盖空槽保留和越界失败两类场景。
- 上线后仅影响新导入任务,无需数据迁移。
- 如需回滚,恢复解析和绑定逻辑即可;本次不涉及表结构变更。
Open Questions
- 历史错误导入的数据是否需要补录或脚本修正;如果需要,应拆成独立变更处理。
- 前端模板文案是否要把
iccid_1 ~ iccid_4明确标注为“槽1 ~ 槽4”;这会影响使用体验,但不阻塞后端修复。