## Context 依据 `docs/engineering/轮询按运营商账户限流技术方案.md` 第三部分第 12、13 节与 14.5 节。 现状:单资产接口 `PATCH /assets/:identifier/polling-status`(`internal/routes/asset.go:140`);`iot_card.Service.BatchUpdatePollingStatus` 仅设备级联内部使用(`asset_polling_service.go:96`);风险停机或已销户自动关闭(`internal/application/cardobservation/network.go:69`);支付成功自动恢复已有部分逻辑。导入任务可参照 `internal/routes/phone_asset_association.go` 的 `/unbind-imports`。生产 2026-10-24:8,420 张风险停机或已销户卡,均关闭轮询。 ## Goals / Non-Goals **Goals:** 人工批量开关轮询;清单可查、可导出、有历史;停机被拒集中处理;套餐生效类入口自动恢复与老系统一致。 **Non-Goals:** 导卡时直接设为不轮询(导卡后用文件导入关闭);调度读取清单表;激活状态计算口径。 ## Decisions 1. **清单只做记录,调度只认 `enable_polling`**:避免为列表扫描卡大表,也避免两处状态不一致;所有写 `enable_polling` 的入口统一经一个"改轮询开关"函数,同事务写清单与审计。 2. **部分唯一索引**:`(asset_type, asset_id) WHERE status = 已关闭`,保证同一资产只有一条已关闭记录;恢复时更新该记录。 3. **批量逐项事务**:每项独立事务,部分失败不影响其他项;返回逐项结果。参照 `batch-update-realname-policy` 的请求与返回格式。 4. **导入任务**:沿用手机号资产解绑导入的上传与任务模型(文件 key 前缀、CSV、逐行结果)。 5. **自动恢复轮询的位置**:订单 `activatePackage`(覆盖支付、后台下单、批量下单、OpenAPI 钱包下单)与改有效期接口;恢复后调用"请求评估"(第 6 个 Change 上线前为现有复机路径)。 6. **存量补写**:迁移中按 `enable_polling = false` 一次性插入,来源按 `gateway_extend` 区分。 7. **停机被拒视图**:基于 `tb_polling_failure_alert` 的筛选视图,不新建表。 ## Risks / Trade-offs - [批量关闭误操作] → 确认框展示影响说明;清单保留操作人与原因,可在清单页批量恢复。 - [存量补写数据量] → 约 8,500 行,一次性迁移可接受。 - [自动恢复与人工关闭意图冲突] → 已定对齐老系统:客户购买或改有效期即恢复;需要长期停用的卡运营须另行处理。 ## Migration Plan 1. 迁移建表并补写存量。2. 测试环境按 tasks 第 8 节核对。3. 维护者发布生产。4. 回退:代码回退;清单表保留。