Admin:将确定的蝦皮非正式规格转换为正式规格 #152

Closed
opened 2026-08-11 14:23:11 +08:00 by ila · 5 comments
Owner

基本信息

  • 类型:数据修复(Admin 商品目录)
  • 父级大工单:#14
  • 所属 MVP / 版本:#15 / 商品目录数据接入后续
  • 阶段:线上蝦皮规格结构化
  • 依赖:#141、#142、#146
  • 状态:进行中

要解决什么

#146 已把三个已处理 Excel 的 2075 个蝦皮商品、33049 条规格导入生产库。由于源文件只有“变种属性值一/二”,没有维度名称,当时严格保留 spec_raw,颜色、尺码为空且 parse_ok=false,因此 Admin 将这些规格显示为“待补”。

用户确认本任务采用“只自动转换能够确定的规格,歧义数据继续待补”的原则。不得为追求全量正式化而猜测颜色和尺码。

做什么 / 不做什么

  • 做:扩展独立 Excel 商品目录工具,按同一商品的整组规格判断两个变种列的维度;只为确定结果填写 color、size 并提交 parse_ok=true。
  • 做:单维规格明显属于尺码时填尺码,否则只有能够确定为颜色/款式时才填颜色;无法确定时保持待补。
  • 做:提供只读预检报告,统计正式化商品/SKU、歧义商品/SKU、各条判定规则命中数和批次大小,不输出商业明细。
  • 做:沿用商品目录接口和 fill_missing,使用新的转换器版本和批次 ID,保留导入审计、人工字段保护和幂等能力。
  • 做:生产执行前重新备份数据库;先在 MySQL 8.4 _test 数据库或生产备份副本演练,再提交生产并做只读核对。
  • 不做:不直接按逗号拆分线上 spec_raw;不改变 spec_raw/spec_key、真实 SKU ID、商品/PDD 关联或人工维护字段。
  • 不做:不强制转换歧义规格;不修改 Client 四接口、采购流程或真实下单开关。
  • 不做:不把 Token、数据库密码、商业规格明细写入代码、日志、工单或归档。

已确认的实现方案

  1. 在 tools/import_catalog_xlsx.py 中保留现有原文组合逻辑,新增独立、可测试的“商品级规格维度判定”步骤。
  2. 判定使用保守的确定性证据:标准尺码符号、明确尺码/体重单位和明确颜色词;按商品聚合整列证据,证据冲突或不足即标记歧义。
  3. 两维商品只有在能够唯一确定尺码列或颜色列时才结构化;另一列按对应维度原样填写。单维商品只有在能够明确判定该维度时才结构化。
  4. 同一商品必须整体采用同一列映射;不允许同一商品逐行改变列含义。
  5. 预检默认只读,并打印汇总与不变量;生产提交仍通过现有 POST /api/v1/integrations/catalog/batches。
  6. 正式化请求只提交确定的 SKU;歧义 SKU 不发送结构化更新。更新策略固定/默认使用 fill_missing,不得覆盖 is_manual=1。
  7. 增加脱敏单元测试,覆盖正向、反向、单维、证据冲突、无证据、混合商品和稳定批次 ID。
  8. 生产执行前后核对:蝦皮商品总数和 SKU 总数不变;spec_raw/spec_key 不变;正式数只增加、待补数按预检减少;人工记录不变;无新增重复规格或失败批次。

预计修改:

  • tools/import_catalog_xlsx.py
  • tools/test_import_catalog_xlsx.py
  • docs/admin/10-商品目录接入接口.md
  • 完成后归档 docs/task/<工单号>-蝦皮规格确定性正式化.md

验收标准

  • 三个 Excel 的只读预检稳定输出总商品 2075、总规格 33049,并分别给出可确定与歧义数量。
  • 两列正向、反向以及单维规格均按商品整体正确判断;冲突或证据不足时保持 parse_ok=false。
  • 转换不改写 spec_raw,不伪造真实 SKU ID,不把歧义规格强制标记为正式。
  • 相同文件和参数重复运行产生稳定请求与新版本批次 ID,可安全断点重跑。
  • fill_missing 只补空字段,人工记录和已有正式字段不被覆盖。
  • Python 单元测试及 Admin 固定 Go 1.23 build/test/vet 通过。
  • MySQL 8.4 _test 演练通过,商品/SKU 总数、规格身份和人工字段不变量成立。
  • 生产执行前备份存在且可读取;生产提交完成后无失败批次,总数不变,正式数与预检一致,歧义数据仍显示待补。
  • Token、数据库密码和商业规格明细未进入日志、工单、Git 或归档。

验证方式

从仓库根目录执行:

python -m unittest tools.test_import_catalog_xlsx
python tools/import_catalog_xlsx.py --dry-run

从 admin/ 使用固定 Go 1.23 执行:

go build ./...
go test ./... -count=1
go vet ./...

使用独立 MySQL 8.4、库名以 _test 结尾验证目录接口补空、人工保护、批次幂等和前后不变量。生产提交命令中的 Token 只从当前进程环境变量读取,不记录明文。

风险和回退

  • 最大风险是误判列含义并批量写反颜色/尺码,因此规则必须保守;不确定即不更新。
  • fill_missing 不提供自动删除语义。生产执行前必须生成可读备份;若发现系统性误判,暂停后续批次,并用本次备份按审批执行数据库级回退。
  • MySQL 与接口写入均属生产变更;预检计数、测试库演练、生产备份任一未通过都不得继续。
## 基本信息 - 类型:数据修复(Admin 商品目录) - 父级大工单:#14 - 所属 MVP / 版本:#15 / 商品目录数据接入后续 - 阶段:线上蝦皮规格结构化 - 依赖:#141、#142、#146 - 状态:进行中 ## 要解决什么 #146 已把三个已处理 Excel 的 2075 个蝦皮商品、33049 条规格导入生产库。由于源文件只有“变种属性值一/二”,没有维度名称,当时严格保留 `spec_raw`,颜色、尺码为空且 `parse_ok=false`,因此 Admin 将这些规格显示为“待补”。 用户确认本任务采用“只自动转换能够确定的规格,歧义数据继续待补”的原则。不得为追求全量正式化而猜测颜色和尺码。 ## 做什么 / 不做什么 - 做:扩展独立 Excel 商品目录工具,按同一商品的整组规格判断两个变种列的维度;只为确定结果填写 `color`、`size` 并提交 `parse_ok=true`。 - 做:单维规格明显属于尺码时填尺码,否则只有能够确定为颜色/款式时才填颜色;无法确定时保持待补。 - 做:提供只读预检报告,统计正式化商品/SKU、歧义商品/SKU、各条判定规则命中数和批次大小,不输出商业明细。 - 做:沿用商品目录接口和 `fill_missing`,使用新的转换器版本和批次 ID,保留导入审计、人工字段保护和幂等能力。 - 做:生产执行前重新备份数据库;先在 MySQL 8.4 `_test` 数据库或生产备份副本演练,再提交生产并做只读核对。 - 不做:不直接按逗号拆分线上 `spec_raw`;不改变 `spec_raw/spec_key`、真实 SKU ID、商品/PDD 关联或人工维护字段。 - 不做:不强制转换歧义规格;不修改 Client 四接口、采购流程或真实下单开关。 - 不做:不把 Token、数据库密码、商业规格明细写入代码、日志、工单或归档。 ## 已确认的实现方案 1. 在 `tools/import_catalog_xlsx.py` 中保留现有原文组合逻辑,新增独立、可测试的“商品级规格维度判定”步骤。 2. 判定使用保守的确定性证据:标准尺码符号、明确尺码/体重单位和明确颜色词;按商品聚合整列证据,证据冲突或不足即标记歧义。 3. 两维商品只有在能够唯一确定尺码列或颜色列时才结构化;另一列按对应维度原样填写。单维商品只有在能够明确判定该维度时才结构化。 4. 同一商品必须整体采用同一列映射;不允许同一商品逐行改变列含义。 5. 预检默认只读,并打印汇总与不变量;生产提交仍通过现有 `POST /api/v1/integrations/catalog/batches`。 6. 正式化请求只提交确定的 SKU;歧义 SKU 不发送结构化更新。更新策略固定/默认使用 `fill_missing`,不得覆盖 `is_manual=1`。 7. 增加脱敏单元测试,覆盖正向、反向、单维、证据冲突、无证据、混合商品和稳定批次 ID。 8. 生产执行前后核对:蝦皮商品总数和 SKU 总数不变;`spec_raw/spec_key` 不变;正式数只增加、待补数按预检减少;人工记录不变;无新增重复规格或失败批次。 预计修改: - `tools/import_catalog_xlsx.py` - `tools/test_import_catalog_xlsx.py` - `docs/admin/10-商品目录接入接口.md` - 完成后归档 `docs/task/<工单号>-蝦皮规格确定性正式化.md` ## 验收标准 - [ ] 三个 Excel 的只读预检稳定输出总商品 2075、总规格 33049,并分别给出可确定与歧义数量。 - [ ] 两列正向、反向以及单维规格均按商品整体正确判断;冲突或证据不足时保持 `parse_ok=false`。 - [ ] 转换不改写 `spec_raw`,不伪造真实 SKU ID,不把歧义规格强制标记为正式。 - [ ] 相同文件和参数重复运行产生稳定请求与新版本批次 ID,可安全断点重跑。 - [ ] `fill_missing` 只补空字段,人工记录和已有正式字段不被覆盖。 - [ ] Python 单元测试及 Admin 固定 Go 1.23 build/test/vet 通过。 - [ ] MySQL 8.4 `_test` 演练通过,商品/SKU 总数、规格身份和人工字段不变量成立。 - [ ] 生产执行前备份存在且可读取;生产提交完成后无失败批次,总数不变,正式数与预检一致,歧义数据仍显示待补。 - [ ] Token、数据库密码和商业规格明细未进入日志、工单、Git 或归档。 ## 验证方式 从仓库根目录执行: ```powershell python -m unittest tools.test_import_catalog_xlsx python tools/import_catalog_xlsx.py --dry-run ``` 从 `admin/` 使用固定 Go 1.23 执行: ```powershell go build ./... go test ./... -count=1 go vet ./... ``` 使用独立 MySQL 8.4、库名以 `_test` 结尾验证目录接口补空、人工保护、批次幂等和前后不变量。生产提交命令中的 Token 只从当前进程环境变量读取,不记录明文。 ## 风险和回退 - 最大风险是误判列含义并批量写反颜色/尺码,因此规则必须保守;不确定即不更新。 - `fill_missing` 不提供自动删除语义。生产执行前必须生成可读备份;若发现系统性误判,暂停后续批次,并用本次备份按审批执行数据库级回退。 - MySQL 与接口写入均属生产变更;预检计数、测试库演练、生产备份任一未通过都不得继续。
Author
Owner

实施进度(2026-08-11)

  • 实现提交:30bdab3。
  • 新增独立 --formalize-specs 模式;普通原始导入不变。正式化批次只提交确定 SKU,强制 fill_missing,歧义商品保持待补。
  • 真实 Excel 预检:源商品 2075、SKU 33049;可正式化商品 1920、SKU 31178;保持待补商品 155、SKU 1871;共 11 批。
  • Python 11 项测试、py_compile、Admin 固定 Go 1.23 build/test/vet 通过。
  • 生产只读基线:SKU 33049,正式 0、待补 33049、人工 0、颜色/尺码均为空;尚无 xlsx-spec-v1 批次。规格身份校验值已记录。
  • 生产备份位于 Git 工作区外:D:\chengma\cmautobuy_private_backups\autobuy-before-152-20260811T143430.sql.gz,4263529 字节,SHA-256 357c54eb21e633cd814e2588fe3bdd6407cb5504abd6689323c93002bd790512,已完整解压读取验证。
  • MySQL 生产账号无权创建隔离 _test 库,测试库未创建;此项未完成。
  • 当前本地没有商品目录 Token,保存的 SSH 登录凭据已失效。尚未发送生产正式化请求,也未直接修改生产业务数据。
  • 下一步:负责人把当前目录 Token 临时设置到本机进程环境变量,或恢复 SSH 后,从服务器受限环境文件供本次进程使用;随后提交 11 个幂等批次并核对总数、正式/待补数、规格身份、人工字段与批次状态。
## 实施进度(2026-08-11) - 实现提交:`30bdab3`。 - 新增独立 `--formalize-specs` 模式;普通原始导入不变。正式化批次只提交确定 SKU,强制 `fill_missing`,歧义商品保持待补。 - 真实 Excel 预检:源商品 2075、SKU 33049;可正式化商品 1920、SKU 31178;保持待补商品 155、SKU 1871;共 11 批。 - Python 11 项测试、py_compile、Admin 固定 Go 1.23 build/test/vet 通过。 - 生产只读基线:SKU 33049,正式 0、待补 33049、人工 0、颜色/尺码均为空;尚无 `xlsx-spec-v1` 批次。规格身份校验值已记录。 - 生产备份位于 Git 工作区外:`D:\chengma\cmautobuy_private_backups\autobuy-before-152-20260811T143430.sql.gz`,4263529 字节,SHA-256 `357c54eb21e633cd814e2588fe3bdd6407cb5504abd6689323c93002bd790512`,已完整解压读取验证。 - MySQL 生产账号无权创建隔离 `_test` 库,测试库未创建;此项未完成。 - 当前本地没有商品目录 Token,保存的 SSH 登录凭据已失效。尚未发送生产正式化请求,也未直接修改生产业务数据。 - 下一步:负责人把当前目录 Token 临时设置到本机进程环境变量,或恢复 SSH 后,从服务器受限环境文件供本次进程使用;随后提交 11 个幂等批次并核对总数、正式/待补数、规格身份、人工字段与批次状态。
Author
Owner

生产执行门禁调整

用户已把现有商品目录 Token 临时填写到本地受 Git 忽略的配置中,并要求继续线上转换。生产账号没有创建 _test 库权限,因此本次无法完成独立 MySQL _test 演练;该缺口不通过放宽数据库权限解决。

本任务不涉及 schema 或 Admin 代码部署,生产现有目录接口已完成 #146 的真实 33049 SKU 导入。采用替代门禁:Python 转换测试、Admin Go build/test/vet、现有目录 fill_missing/人工保护测试、真实 Excel dry-run、生产只读基线、完整 mysqldump 备份与 gzip/SHA-256 校验均已通过;正式请求仍逐批事务、幂等、首错停止。提交后必须核对总 SKU=33049、正式=31178、待补=1871、人工=0、规格身份 XOR/SUM 不变且 11 批全部 succeeded。若任一不变量不成立,立即停止并按备份回退,不继续归档。

## 生产执行门禁调整 用户已把现有商品目录 Token 临时填写到本地受 Git 忽略的配置中,并要求继续线上转换。生产账号没有创建 `_test` 库权限,因此本次无法完成独立 MySQL `_test` 演练;该缺口不通过放宽数据库权限解决。 本任务不涉及 schema 或 Admin 代码部署,生产现有目录接口已完成 #146 的真实 33049 SKU 导入。采用替代门禁:Python 转换测试、Admin Go build/test/vet、现有目录 `fill_missing`/人工保护测试、真实 Excel dry-run、生产只读基线、完整 mysqldump 备份与 gzip/SHA-256 校验均已通过;正式请求仍逐批事务、幂等、首错停止。提交后必须核对总 SKU=33049、正式=31178、待补=1871、人工=0、规格身份 XOR/SUM 不变且 11 批全部 succeeded。若任一不变量不成立,立即停止并按备份回退,不继续归档。
Author
Owner

生产执行结果

  • 11/11 个 xlsx-spec-v1 批次 succeeded,0 failed、0 processing。
  • SKU 总数 33049 不变;正式规格 31178,待补 1871;待补商品 155。
  • 批次统计:created 0、updated/filled 31178、skipped 0、manual_skipped 0、stale_skipped 0。
  • 正式但颜色/尺码同时为空 0;待补但已有结构化字段 0。
  • goods_id/spec_key/spec_raw 身份校验:XOR 1848061991、SUM 70664155756801,与执行前完全一致。
  • shopee_products 总数仍为 5451;正式化请求没有提交商品、PDD 商品或关联。
  • 生产备份已在执行前完成并验证,未触发回退。

实现和生产数据修复均已完成,下一步写入 docs/task/152-蝦皮规格确定性正式化.md 并提交归档。独立 MySQL _test 因生产账号无建库权限未执行,已由前一条评论记录替代门禁和理由。

## 生产执行结果 - 11/11 个 `xlsx-spec-v1` 批次 succeeded,0 failed、0 processing。 - SKU 总数 33049 不变;正式规格 31178,待补 1871;待补商品 155。 - 批次统计:created 0、updated/filled 31178、skipped 0、manual_skipped 0、stale_skipped 0。 - 正式但颜色/尺码同时为空 0;待补但已有结构化字段 0。 - `goods_id/spec_key/spec_raw` 身份校验:XOR `1848061991`、SUM `70664155756801`,与执行前完全一致。 - `shopee_products` 总数仍为 5451;正式化请求没有提交商品、PDD 商品或关联。 - 生产备份已在执行前完成并验证,未触发回退。 实现和生产数据修复均已完成,下一步写入 `docs/task/152-蝦皮规格确定性正式化.md` 并提交归档。独立 MySQL `_test` 因生产账号无建库权限未执行,已由前一条评论记录替代门禁和理由。
Author
Owner

完成与归档

  • 实现提交:30bdab3 feat: 确定性转换蝦皮待补规格 (#152)
  • 归档提交:2629e41 docs: 归档任务 #152
  • 本地归档:docs/task/152-蝦皮规格确定性正式化.md
  • 当前状态:实现、生产数据修复、核对和归档均已完成,等待用户验收。

未验证项已在归档明确记录:未执行独立 MySQL _test 演练、未逐行人工检查全部正式规格、未执行备份恢复演练。

## 完成与归档 - 实现提交:`30bdab3` `feat: 确定性转换蝦皮待补规格 (#152)` - 归档提交:`2629e41` `docs: 归档任务 #152` - 本地归档:`docs/task/152-蝦皮规格确定性正式化.md` - 当前状态:实现、生产数据修复、核对和归档均已完成,等待用户验收。 未验证项已在归档明确记录:未执行独立 MySQL `_test` 演练、未逐行人工检查全部正式规格、未执行备份恢复演练。
Author
Owner

用户于 2026-08-12 明确验收通过。已确认本地归档 docs/task/152-蝦皮规格确定性正式化.md 存在,现关闭工单。

用户于 2026-08-12 明确验收通过。已确认本地归档 `docs/task/152-蝦皮规格确定性正式化.md` 存在,现关闭工单。
ila closed this issue 2026-08-12 10:32:06 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chengma/cmautobuy#152