批量换货脚本
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m26s

This commit is contained in:
2026-07-22 19:09:28 +09:00
parent c58773e35b
commit c7f8b4c702
5 changed files with 986 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
# 批量换货脚本
该脚本读取两列 CSV逐行调用 `POST /api/admin/exchanges` 执行换货。脚本固定使用:
- `flow_type=direct`:只支持直接换货,接口创建换货单后会立即完成换货。
- `migrate_data=true`:必须执行全量数据迁移,不能通过参数关闭。
全量迁移由现有换货接口在同一事务中执行,包括钱包余额、套餐使用记录、累计充值字段和资产标签。脚本仅使用 Python 标准库,不需要安装依赖。
默认只预演,必须增加 `--execute` 才会真实换货。
## CSV 格式
首行表头可选,第一列填写旧资产标识,第二列填写新资产标识:
```csv
old_identifier,new_identifier
89860000000000000001,89860000000000000101
89860000000000000002,89860000000000000102
```
支持表头:
- 英文:`old_identifier,new_identifier``old_asset_identifier,new_asset_identifier`
- 中文:`旧资产标识,新资产标识``旧资产,新资产`
旧、新资产标识均使用换货接口已有的识别规则:物联网卡支持 ICCID、接入号、虚拟号设备支持虚拟号、IMEI、SN。
脚本会在请求前拦截:
- 列数不是两列,或任一列为空。
- 同一行新旧资产相同。
- 旧资产重复,或新资产重复。
- 同一资产在本批次中既作为旧资产又作为新资产。该情况会受到执行顺序影响,因此整批终止。
## 预演
物联网卡示例:
```bash
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv scripts/batch_exchange/exchanges.example.csv \
--asset-type iot_card
```
设备批次将 `--asset-type` 改为 `device`。同一个 CSV 批次只能使用一种资产类型;新资产必须与旧资产类型一致,否则接口会拒绝该行。
预演只校验 CSV 并展示最多五条请求示例,不需要 Token也不会调用接口。输出中会明确显示 `direct``migrate_data=true`
## 使用已有 Token 执行
推荐通过环境变量传递 Token避免进入命令历史
```bash
JUNHONG_ADMIN_TOKEN='<后台Access Token>' \
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--execute
```
## 使用账号自动登录后执行
未提供 Token 时,可以使用后台账号调用 `/api/admin/login` 自动获取 Token
```bash
JUNHONG_ADMIN_USERNAME='<后台账号>' \
JUNHONG_ADMIN_PASSWORD='<后台密码>' \
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--execute
```
也可以使用 `--token``--username``--password` 参数。密码优先通过环境变量或交互输入,避免保存在 Shell 历史中。
## 换货原因和备注
脚本默认使用 `批量直接换货` 作为换货原因。可按整批覆盖原因和备注:
```bash
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--exchange-reason '故障卡批量换货' \
--remark '2026年7月批次' \
--execute
```
## 结果文件
默认在输入 CSV 同目录生成:
```text
原文件名_换货结果_YYYYMMDD_HHMMSS.csv
```
结果包含新旧资产标识、成功或失败状态、HTTP 状态码、业务错误码、错误消息、换货单 ID、换货单号、迁移完成状态和迁移余额。每处理一条都会立即刷新文件中途中断时已完成的结果不会丢失。
为避免覆盖历史结果,`--output` 指定的文件已经存在时脚本会直接报错。
## 其他参数和执行约束
- `--timeout`:单次请求超时秒数,默认 `30`
- `--interval`:每次换货后的等待秒数,默认 `0.2`
- `--execute`:显式开启真实换货。
每组资产单独调用一次接口,脚本不会自动重试 POST 请求。接口可能已经成功提交事务但客户端没有收到响应,自动重试可能造成误判;失败项应先查询换货单或资产状态,再决定是否单独重跑。
脚本不会回滚前面已经成功的行。执行前应先预演并确认完整映射;执行后根据结果 CSV 逐条核对失败项。