Files
cmautobuy/docs/task/146-商品目录Excel分批提交脚本.md
T

82 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 146 Admin:编写三个已处理 Excel 的商品目录分批提交脚本
- 类型:需求
- 父级大工单:#14
- 所属 MVP / 版本:#15 / 商品目录数据接入后续
- 状态:已完成
- 日期:2026-08-11
- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/146
## 背景与目标
三个已处理工作簿是一行一个蝦皮规格,共 2075 个蝦皮商品、33049 条唯一规格,
同时包含 PDD 商品 ID、链接、店铺以及两边的关联。需要先把重复的商品行聚合,再按
商品目录接口的商品数、SKU 数和请求体大小限制安全分批,并允许失败后幂等重跑。
## 最终方案
新增独立 Python 命令行工具。工具以只读方式解析 `在线商品` 工作表,严格检查列、
固定字段、规格唯一性和 PDD ID/URL 一致性;按蝦皮商品聚合,使一个商品的全部规格
不跨批,并按 PDD ID 在批内去重。默认每批最多 200 个蝦皮商品,同时动态检查接口的
500 商品、5000 SKU、5 MB 上限。
文件没有真实蝦皮 SKU ID,也没有可判断两个变种列含义的维度名称。工具只按原列顺序
组合 `spec_raw`,不填写 SKU ID、颜色、尺码或 PDD 规格价格。PDD 链接去掉跟踪参数,
只保留稳定的 `goods_id`。
批次 ID 同时包含转换器版本、文件内容、批量大小和更新策略的摘要,观测时间取批内
Excel 最大更新时间;相同文件和参数会产生完全相同的请求。Token 只读取环境变量,
临时错误指数退避,业务错误立即停止。实现与建单方案一致。
用户随后明确把范围扩展到生产执行。部署前将生产 MySQL 备份到
`/opt/cmautobuy/backups/autobuy-before-e4385ac-20260811T034853Z.sql.gz` 并通过 gzip
校验;按提交 `e4385ac` 构建 Linux amd64 二进制,SHA-256 为
`287e5b9484f9e827cbed3325c8c3c31b4209bca487692f1db6fa89fcd4ff9bd7`,部署到
`/opt/cmautobuy/releases/e4385ac/`。服务器随机生成 32 字节目录 Token,只写入权限
`600` 的 `/etc/cmautobuy/admin.env`,未输出明文。服务启动后 schema v10 自检通过,
再通过 HTTPS 顺序提交全部 11 个批次。
## 改了哪些
- `tools/import_catalog_xlsx.py`:Excel 聚合、批次规划、dry-run、鉴权提交、重试和汇总。
- `tools/test_import_catalog_xlsx.py`:脱敏工作簿的聚合、幂等、分批、冲突和重试测试。
- `tools/requirements-catalog-import.txt`:固定 `openpyxl` 版本。
- `docs/admin/10-商品目录接入接口.md`:补充安装、预检、真实提交和断点重跑说明。
- `/opt/cmautobuy/releases/e4385ac/`:新增生产发布目录并原子切换当前 Admin。
- `/etc/cmautobuy/admin.env`:增加目录来源与专用 Token,权限保持 `600`。
- 生产 MySQL `autobuy`:写入 11 个成功批次的商品目录数据和导入摘要。
## 验收结果
| 验收标准 | 结果 |
|---|---|
| 三个真实样本得到 2075 个蝦皮商品、33049 条唯一规格 | 通过 |
| 商品 SKU 不跨批,PDD 批内去重,全部批次满足三项接口限制 | 通过;共 11 批,最大请求 1022285 字节 |
| 不伪造 SKU ID、颜色尺码、PDD 规格和价格 | 通过 |
| 相同文件和参数生成相同批次 ID、时间和 JSON | 通过 |
| 不同批量大小或更新策略使用不同批次 ID | 通过 |
| Token 只读取环境变量且不输出 | 通过 |
| dry-run、临时错误重试、业务错误停止和进度汇总可用 | 通过 |
| Python 自动化测试和 Admin Go 1.23 回归通过 | 通过 |
| 部署前生产数据库备份存在且 gzip 可读 | 通过;备份 1183828 字节,权限 `600` |
| 生产运行提交 `e4385ac` 对应二进制且 schema v10 完整 | 通过 |
| 生产目录 Token 受限保存且鉴权行为正确 | 通过;错误 Token 返回 `401 UNAUTHORIZED` |
| 11 个真实批次全部完成且无失败或进行中记录 | 通过;11 succeeded、0 failed、0 processing |
| 真实数据计数与三个工作簿一致 | 通过;2075 商品处理、33049 SKU、2075 关联 |
## 测试
- 执行的命令:`python -m unittest tools/test_import_catalog_xlsx.py -v`。
- 结果:5 个测试通过。
- 执行的命令:`python tools/import_catalog_xlsx.py --dry-run`。
- 结果:三个真实样本解析成功,分别生成 5、5、1 个批次;最大请求分别为 1022285、794046、350890 字节,未发送请求。
- 执行的命令:在 `admin/` 使用 `GOTOOLCHAIN=go1.23.0` 执行 `go build ./...`、`go test ./... -count=1`、`go vet ./...`。
- 结果:全部通过。
- 执行的操作:生产备份、Linux amd64 构建与哈希核对、上传和原子切换、systemd/HTTPS/鉴权/schema 检查、11 批真实提交及 MySQL 汇总查询。
- 结果:Admin、MySQL、Nginx 均 active;schema v10 只记录一次;11/11 批次成功。目录摘要为蝦皮商品新增 2057/更新 18、SKU 新增 33049、PDD 新增 1883/更新 114、关联新增 2075;失败计数为 0。
- **没验证到的部分**:未使用网页登录账号逐行人工查看全部导入商品;接口响应、导入摘要和数据库总数已核对,未执行备份恢复演练。
## 相关提交
- `acfa699` 增加商品目录 Excel 分批提交脚本