feat: 不轮询清单与批量开关轮询
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m35s

- 新增不轮询清单 tb_card_polling_pause(迁移 000256 补写存量),所有改 enable_polling 的入口同事务写清单
- 卡、设备勾选批量开关轮询(单次 500,逐项结果,开启跳过风险停机与已销户)与 CSV 文件导入
- 订单套餐生效、改有效期后自动恢复轮询并按规则评估复机
- 不轮询清单查询与导出;卡、设备列表与导出增加是否轮询
- 失败告警停机被拒视图、导出与批量关闭轮询;开关轮询影响说明

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
邹进
2026-10-26 03:07:20 +09:00
parent a4e3fe4d8f
commit 7ddb9312e3
45 changed files with 2250 additions and 50 deletions

View File

@@ -1,43 +1,43 @@
## 0. 前置确认
- [ ] 0.1 停机被拒视图实施前确认第 5、6 个 Change 已上线;开关与清单部分可先行。
- [x] 0.1 停机被拒视图实施前确认第 5、6 个 Change 已上线;开关与清单部分可先行。(第 5 个 Change 已部署测试环境,第 6 个 Change 已实现并部署测试环境)
## 1. 迁移与模型
- [ ] 1.1 新增成对迁移:建 `tb_card_polling_pause`(资产类型、资产 ID、ICCID 或 IMEI、运营商账户、状态、关闭来源、原因、操作人、关闭时间、导入任务 ID、恢复来源、恢复人、恢复时间;部分唯一索引 `(asset_type, asset_id) WHERE status = 已关闭`);down 删表。
- [ ] 1.2 同迁移补写存量:`enable_polling = false` 的卡与设备,风险停机或已销户记"风险停机或已销户自动关闭",其余记"历史数据"。
- [ ] 1.3 新增 model 与 Store。
- [x] 1.1 新增成对迁移:建 `tb_card_polling_pause`(资产类型、资产 ID、ICCID 或 IMEI、运营商账户、状态、关闭来源、原因、操作人、关闭时间、导入任务 ID、恢复来源、恢复人、恢复时间;部分唯一索引 `(asset_type, asset_id) WHERE status = 已关闭`);down 删表。(000256;同迁移另建 tb_polling_status_import_task)
- [x] 1.2 同迁移补写存量:`enable_polling = false` 的卡与设备,风险停机或已销户记"风险停机或已销户自动关闭",其余记"历史数据"。(测试库补写 4 张卡:risk_auto 2、history 2,与关闭轮询卡数一致)
- [x] 1.3 新增 model 与 Store。(model.CardPollingPause / PollingStatusImportTask;读取走 internal/query/pollingpause)
## 2. 统一的轮询开关写入
- [ ] 2.1 新增"改轮询开关(资产、目标状态、来源、原因、操作人)":同事务写 `enable_polling`、清单与审计,提交后调用生命周期移入或移出。
- [ ] 2.2 改造全部入口经此函数:单资产接口、风险停机或已销户自动关闭(`network.go`)、设备级联、自动恢复、告警页关闭。
- [x] 2.1 新增"改轮询开关(资产、目标状态、来源、原因、操作人)":同事务写 `enable_polling`、清单与审计,提交后调用生命周期移入或移出。(infrastructure/pollingpause.Record 在调用方事务内写清单,来源与原因经 ctx 的 Origin 传入;卡与设备开关、设备级联各自同事务写 enable_polling、清单与审计,提交后经生命周期移入或移出)
- [x] 2.2 改造全部入口经此函数:单资产接口、风险停机或已销户自动关闭(`network.go`)、设备级联、自动恢复、告警页关闭。(单资产接口、设备级联(来源 cascade)、风险停机或已销户自动关闭(network.go 与停复机终态 TerminalPollingDisabler)、批量、导入、自动恢复、告警页关闭均经 Record;开启时风险停机或已销户的卡拒绝或跳过)
## 3. 批量与导入
- [ ] 3.1 `POST /iot-cards/batch-update-polling-status`、`POST /devices/batch-update-polling-status`:单次 500、数据权限、逐项事务与结果、批量开启跳过风险停机与已销户。
- [ ] 3.2 文件导入:`POST /polling-status-imports`、`GET /polling-status-imports`、`GET /polling-status-imports/:id`;异步逐行处理与结果。
- [x] 3.1 `POST /iot-cards/batch-update-polling-status`、`POST /devices/batch-update-polling-status`:单次 500、数据权限、逐项事务与结果、批量开启跳过风险停机与已销户。(逐项结果:成功、跳过(已是目标状态、风险停机或已销户)、失败、无权限或资产不存在;数据权限用 ApplyStrictShopFilter,企业账号拒绝;返回本次影响说明)
- [x] 3.2 文件导入:`POST /polling-status-imports`、`GET /polling-status-imports`、`GET /polling-status-imports/:id`;异步逐行处理与结果。(仅平台账号创建;上传 purpose=polling_status_import;Worker 任务 polling:status_import 逐行处理,每行独立,部分成功不回滚,逐行结果写 result_items)
## 4. 自动恢复轮询
- [ ] 4.1 `order/service.go` `activatePackage` 套餐生效后:关闭轮询且非风险停机、已销户的卡或设备先恢复轮询(来源"支付或下单生效"),再请求评估(第 6 个 Change 前为现有复机路径)。
- [ ] 4.2 改有效期接口:保存后资产有生效套餐时同样恢复(来源"改有效期")。
- [x] 4.1 `order/service.go` `activatePackage` 套餐生效后:关闭轮询且非风险停机、已销户的卡或设备先恢复轮询(来源"支付或下单生效"),再请求评估(第 6 个 Change 前为现有复机路径)。(订单 6 个激活入口事务提交后 afterOrderActivated:本单激活主套餐时恢复轮询(来源 order,风险停机或已销户不恢复),再按规则评估复机;API 与 Worker(批量下单)都注入)
- [x] 4.2 改有效期接口:保存后资产有生效套餐时同样恢复(来源"改有效期")。(UpdatePackageExpiresAt 保存后有生效中主套餐时恢复(来源 expiry_change)并请求复机评估)
## 5. 查询、筛选与导出
- [ ] 5.1 `GET /card-polling-pauses`(筛选与分页);导出场景 `polling_pause`;清单页勾选批量开启复用 3.1。
- [ ] 5.2 卡列表、设备列表 Query 增加 `enable_polling` 筛选,导出带该字段。
- [ ] 5.3 开关轮询影响说明随接口文档与返回提供。
- [x] 5.1 `GET /card-polling-pauses`(筛选与分页);导出场景 `polling_pause`;清单页勾选批量开启复用 3.1。(GET /card-polling-pauses 仅平台账号;导出场景 polling_pause 与列表同筛选;清单页批量开启复用 3.1)
- [x] 5.2 卡列表、设备列表 Query 增加 `enable_polling` 筛选,导出带该字段。(卡、设备列表与导出 enable_polling 筛选;卡与设备导出最后一列追加「是否轮询」,按冻结表头末列识别版本,历史任务重导出列序不变)
- [x] 5.3 开关轮询影响说明随接口文档与返回提供。(GET /polling-status/impact;批量与导入接口文档附影响说明,批量返回 impact)
## 6. 停机被拒视图
- [ ] 6.1 `GET /polling-failure-alerts?view=stop_refused` 与展示字段;导出场景 `polling_stop_refused_alert`。
- [ ] 6.2 `POST /polling-failure-alerts/close-polling`:单次 500,经统一开关写入,来源"停机被拒告警处理",告警状态改为已关闭轮询。
- [x] 6.1 `GET /polling-failure-alerts?view=stop_refused` 与展示字段;导出场景 `polling_stop_refused_alert`。(view=stop_refused:check_type=stop_resume、停机方向、终态或业务错误或失败数≥停复机告警阈值;附设备、网络状态、停机原因、是否轮询、有无生效套餐、处理人;导出场景 polling_stop_refused_alert;告警检查类型筛选补 stop_resume)
- [x] 6.2 `POST /polling-failure-alerts/close-polling`:单次 500,经统一开关写入,来源"停机被拒告警处理",告警状态改为已关闭轮询。(只关告警对应卡自身;成功或已关闭的告警改为已关闭轮询并记处理人与备注)
## 7. 编译与规范校验
- [ ] 7.1 `gofmt -w`;`go build ./cmd/api ./cmd/worker` 通过;重新生成接口文档。
- [ ] 7.2 `openspec validate add-polling-pause-list-and-batch-toggle` 与 `openspec doctor --json` 通过。
- [x] 7.1 `gofmt -w`;`go build ./cmd/api ./cmd/worker` 通过;重新生成接口文档。
- [x] 7.2 `openspec validate add-polling-pause-list-and-batch-toggle` 与 `openspec doctor --json` 通过。(validate 通过;当前 openspec 无 doctor 命令)
## 8. 测试环境验证(自动化测试为 N/A,按 ENG-TEST-001)