feat: 蝦皮 Excel 报表导入 (#38)

蝦皮数据模块此前整个是骨架,四个入口全返回 501,excelize 连依赖都没装。
本工单做导入和列表,Save/Delete/Collect 保持 501。

真实样本实测:5195 个商品 / 6092 个 SKU,23 行解析失败。

upsert 白名单式,pdd_goods_url / pdd_goods_id 既不在 INSERT 列清单里
也不在 DO UPDATE SET 里。报表没有这两列,写进去就是写空值——操作员
攒几周的 PDD 链接会被一次导入洗光,而且不报错,等到建采购任务才发现。
有独立测试守着:往 DO UPDATE SET 里加回这一行,测试立刻变红。

按 sheet 名字取「最佳表現商品」,不用第 0 个。工作簿有 5 个 sheet,
另外 4 个是广告报表,连 商品規格ID 列都没有;蝦皮调顺序时按下标
会静默导入一张完全不相干的表。

按列名找索引。40 列里 32 列是统计指标,蝦皮加一列所有列号就错位,
而且不报错——会把「點擊率」当成「商品規格」存进去。

规格解析三种格式:含【】53.4%、逗号+空格 26.4%、只有逗号 20.2%,
只认【】会漏掉 46.6%。括号不配对(21 行)和右半整个被【】包住(2 行)
一律判整体失败,不逐段硬凑——错法不统一,针对每种错法写规则等于在猜,
而且没有人工核对过的正确答案可验证。失败时 color/size/advice 必须全空,
原文存进 spec_raw 交人工补。

不写 DELETE + INSERT 的全量替换,将来手动新增的 SKU 会被删掉。

excelize v2.9.1 的 go 指令正好是 1.23.0,与项目固定版本一致。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
chengma
2026-08-08 09:57:12 +08:00
co-authored by Claude Opus 5
parent 18770f25e1
commit e29d6683ad
10 changed files with 1211 additions and 91 deletions
+22 -27
View File
@@ -3,37 +3,32 @@
自动化测试用的**脱敏小样本**放这里,**要提交进 Git**。
否则别人拉下仓库跑 `go test ./...` 会失败。
## 需要准备的文件
## 蝦皮 Excel 导入测试(工单 #38)
| 文件 | 用途 | 状态 |
|---|---|---|
| `shopee_sample.xlsx` | Excel 导入测试 | **待制作** |
**没有提交静态的 `shopee_sample.xlsx`。** 固件改成用 `excelize` 在
`admin/service/shopee_import_test.go` 里现造(见 `buildShopeeWorkbook`),
测试跑到时临时生成、测试结束自动清理。
## 怎么制作 `shopee_sample.xlsx`
选择现造而不是提交一个二进制文件的原因:xlsx 是二进制格式,PR 里看不出
改了什么,审查只能"信任"文件内容;现造的话,固件长什么样直接写在
测试代码里,一眼能看到覆盖了哪些场景。
从真实报表(`raw_data/蝦皮数据样本.xlsx`,需向项目负责人索取)里裁出来:
覆盖的场景(对应工单 #38 的要求):
1. **只保留几十行**,但要覆盖这几种情况:
- 商品汇总行(`商品規格ID` 是 `-`);
- SKU 行,规格原文用**带【】**的格式,如 `黑色,M【建議40-50公斤】`;
- SKU 行,规格原文用**空格分隔**的格式,如 `卡其色拼黑色,L 建議50-57.5kg`;
- 至少一行**故意写成解析不了的格式**,用来验证 `parse_ok=0` 且不瞎猜。
- 商品汇总行(`商品規格ID` 是 `-`);
- SKU 行,规格原文用**带【】**的格式,如 `黑色,M【建議40-50公斤】`;
- SKU 行,规格原文用**空格分隔**的格式,如 `卡其色拼黑色,L 建議50-57.5kg`;
- SKU 行,只有颜色和尺码、没有建议,如 `黑色,M`;
- 颜色自己也带【】的格式,如 `黑色 【夏裝單件T恤】,L 【57.5/70公斤】`;
- 括号不配对的脏数据(真实样本里的 21~23 行),验证 `parse_ok=0`
且不瞎猜;
- 表头缺列、sheet 名不对;
- 已有人工填的 `pdd_goods_url` / `pdd_goods_id`,验证导入不覆盖;
- 已有 `is_manual = 1` 的人工新增 SKU,验证导入不删除;
- 同一个文件导入两次,验证不产生重复行。
前两种在真实数据里各占 53.4% 和 46.6%,两种都必须有用例。
2. **删掉全部商业指标列**——销售额、曝光次数、点击数、转化率、
买家数、回购率等等。导入根本用不到这些,留着就是泄露。
只保留:`商品ID`、`商品名稱`、`商品當前狀態`、`商品規格ID`、
`商品規格`、`規格當前狀態`、`商品選項貨號`、`主商品貨號`。
3. **商品名称换成无意义的占位文字**,如 `测试商品A`、`测试商品B`。
4. 记下期望结果,写进测试断言(例如 3 商品 + 8 SKU + 1 行解析失败)。
## 为什么不直接用真实报表
- 1.9MB,每次跑测试都读一遍太慢;
- 含逐商品的台币销售额,属于商业数据,已在 `.gitignore` 里排除。
真实样本 `raw_data/蝦皮数据样本.xlsx`(需向项目负责人索取,
含商业数据,已在 `.gitignore` 里排除)仍然用于**人工验证**,
不用于自动化测试——1.9MB,每次跑测试都读一遍太慢。
相关规定见 `docs/admin/06-quality-security.md` §2.1。