T57 从 cmautobuy 线上库导入 PDD 与蝦皮商品 #70

Closed
opened 2026-08-23 23:45:29 +08:00 by ila · 3 comments
Owner

原始需求摘要

用户于 2026-08-23 要求:把 D:\chengma\cmautobuy\admin 线上 MySQL 中的蝦皮商品和 PDD 商品同步到 GoAuto 本地 MySQL 8。用户明确确认:目标库已存在相同 goods_id 或 shopee_item_id 时,以线上 cmautobuy 数据覆盖本机商品档案。

目标

实现一个独立、幂等、默认只读预检的命令行导入工具:

  1. 从 cmautobuy 线上 MySQL 只读一致性快照读取有效 PDD 商品、蝦皮商品、蝦皮 SKU 和当前蝦皮→PDD 商品关联。
  2. 转换为 GoAuto 当前 pdd_product 与 shopee_product 数据契约。
  3. 默认 --dry-run,输出新增、覆盖、冲突、跳过和无法转换的非敏感汇总。
  4. 只有显式 --apply 才在 GoAuto 本地 MySQL 单事务写入;目标同键记录按用户确认覆盖。
  5. 可重复执行,不产生重复商品。

非目标

  • 不导入或修改 SYB 商品、采集/采购任务、PDD 订单、物流、用户、设备、规则或历史状态。
  • 不导入 cmautobuy 旧 spec_mappings / AI 决策;旧项目组合 SKU 映射与 GoAuto 规格值映射语义不同,避免静默买错。
  • 不持续双库同步,不把导入挂到服务启动或数据库 schema migration。
  • 不修改 Android Agent 或 Web 页面。
  • 本工单不执行付款或创建订单。
  • 未经用户查看 dry-run 精确影响并再次确认,不执行 --apply。

前置依赖与并行关系

  • 依赖 #31 PDD 商品档案、#40/#41 蝦皮商品档案及规格 JSON 契约。
  • 与 #69 无代码依赖;本工单仅修改 Server 的离线导入命令和相关长期文档,可独立实施。
  • 来源项目数据模型以其当前代码和线上 information_schema 只读检查共同确认,不能只假定部署库已升级到仓库最新版本。

子项目影响

  • server/:新增独立导入命令、转换和事务写入逻辑、单元/集成测试。
  • Wiki:Architecture、Business-Rules-and-Glossary、Developer-Workflow 或对应运维说明。
  • 不修改 web/、android/、共享 Agent API 和现有表结构。

已确认覆盖与转换规则

PDD 商品

  • 业务键:goods_id。
  • URL 中的 goods_id 必须和字段一致;无效或不一致时跳过并报告。
  • title、shop_name、URL 和可转换规格以来源覆盖本机。
  • 旧 skus_json 转为 GoAuto 通用 specs_json:按维度顺序聚合唯一规格值;角色为 color/size/other;可选择状态取该值是否存在任一可用组合。
  • 颜色价格只在同一颜色的所有有效非空价格唯一时写入;出现多个不同价格时价格留空、商品保持 pending 并报告,禁止猜最低或最高价。
  • 来源 collected 且规格转换无冲突时目标状态为 active;其余为 pending。来源软删除记录默认跳过。
  • 来源没有的销量、评价数量保持目标 NULL;覆盖现有记录时清为 NULL,体现“来源覆盖”。
  • 人工停用的本机 PDD 商品不得被导入自动启用:目标原状态为 disabled 时保留 disabled。

蝦皮商品

  • 业务键:来源 goods_id → 目标 shopee_item_id。
  • 标题、店铺、图片和规格以来源覆盖本机;参考售价来源不存在时清为 NULL,币种使用 GoAuto 系统配置,缺省 TWD。
  • 聚合来源 shopee_skus 的唯一颜色/尺码:解析成功字段写入对应维度;is_manual=1 标为 manual,其他标为 import;解析失败或空字段不猜测并报告。
  • 来源当前 pdd_goods_id 通过目标 pdd_product.goods_id 换算为数字 pdd_product_id;来源为空时清除本机关联,来源目标无效/缺失时本条标为冲突且不静默关联。
  • 来源软删除蝦皮商品默认跳过;目标同 item ID 的存活记录覆盖。目标只有软删除记录时不自动恢复,报告冲突,避免绕过恢复语义。

安全和事务

  • 来源连接只允许 MySQL 且使用只读账号;密码不接受命令行参数,不输出 DSN。
  • 来源配置从独立未跟踪配置或环境变量读取;目标读取 GoAuto config.yaml / 安全环境配置。
  • dry-run 是默认模式且不写两边数据库。
  • apply 开始前再次校验来源/目标 schema;来源使用一致性只读事务,目标使用单个事务。
  • 写入后在提交前校验唯一键、关联完整性、JSON 和逐类计数守恒;失败整体回滚。
  • 报告只含商品业务 ID、动作和非敏感原因,不含凭据、个人信息、原始响应、控件树或截图。
  • 真正 apply 属于覆盖本地数据的高风险动作,必须在 dry-run 后再次等待用户确认。

验收标准

  • 默认运行不写数据库,输出稳定 dry-run 汇总和逐条冲突。
  • 来源/目标 schema 不满足要求时在写入前明确失败。
  • PDD 商品可以新增或按 goods_id 覆盖,且不产生重复。
  • 蝦皮商品可以新增或按 shopee_item_id 覆盖,并正确换算 PDD 数字关联。
  • PDD SKU 组合正确聚合为通用规格;同颜色多价格不猜测。
  • 蝦皮 SKU 正确聚合颜色/尺码;无法解析的内容不猜测。
  • 不导入旧规格映射、任务、订单、SYB 或其他范围外数据。
  • 来源连接无写权限,目标 apply 单事务失败回滚。
  • Go 单元测试、构建、项目 Server 验证、严格 harness 检查通过。
  • 工单回写实现、真实测试、未验证项、提交哈希和文档 revision。
  • dry-run 真实数量交给用户审核;未再次确认前不运行 apply。

设计证据

无 Web/Android 页面变化,不需要 QuantUX/HTML。采用本工单中的数据映射、覆盖、事务和安全设计作为实施门禁。

风险与回退

  • 最大风险是把旧组合 SKU 误转成错误颜色价格或映射;通过唯一价格规则、旧映射不迁移和提交前校验控制。
  • 来源和目标不支持分布式事务;先在来源只读快照完整装载,再开启目标单事务。
  • apply 前应备份本地两张商品表;若后续需要回退,依据备份和导入报告另行确认执行,不在本命令自动删除数据。

文档影响

需要更新 Wiki:记录离线导入入口、配置来源、dry-run/apply 命令、覆盖规则、非目标、安全边界和验证方式;再通过 harness 同步核心镜像。

## 原始需求摘要 用户于 2026-08-23 要求:把 `D:\chengma\cmautobuy\admin` 线上 MySQL 中的蝦皮商品和 PDD 商品同步到 GoAuto 本地 MySQL 8。用户明确确认:目标库已存在相同 `goods_id` 或 `shopee_item_id` 时,以线上 cmautobuy 数据覆盖本机商品档案。 ## 目标 实现一个独立、幂等、默认只读预检的命令行导入工具: 1. 从 cmautobuy 线上 MySQL 只读一致性快照读取有效 PDD 商品、蝦皮商品、蝦皮 SKU 和当前蝦皮→PDD 商品关联。 2. 转换为 GoAuto 当前 `pdd_product` 与 `shopee_product` 数据契约。 3. 默认 `--dry-run`,输出新增、覆盖、冲突、跳过和无法转换的非敏感汇总。 4. 只有显式 `--apply` 才在 GoAuto 本地 MySQL 单事务写入;目标同键记录按用户确认覆盖。 5. 可重复执行,不产生重复商品。 ## 非目标 - 不导入或修改 SYB 商品、采集/采购任务、PDD 订单、物流、用户、设备、规则或历史状态。 - 不导入 cmautobuy 旧 `spec_mappings` / AI 决策;旧项目组合 SKU 映射与 GoAuto 规格值映射语义不同,避免静默买错。 - 不持续双库同步,不把导入挂到服务启动或数据库 schema migration。 - 不修改 Android Agent 或 Web 页面。 - 本工单不执行付款或创建订单。 - 未经用户查看 dry-run 精确影响并再次确认,不执行 `--apply`。 ## 前置依赖与并行关系 - 依赖 #31 PDD 商品档案、#40/#41 蝦皮商品档案及规格 JSON 契约。 - 与 #69 无代码依赖;本工单仅修改 Server 的离线导入命令和相关长期文档,可独立实施。 - 来源项目数据模型以其当前代码和线上 `information_schema` 只读检查共同确认,不能只假定部署库已升级到仓库最新版本。 ## 子项目影响 - `server/`:新增独立导入命令、转换和事务写入逻辑、单元/集成测试。 - Wiki:Architecture、Business-Rules-and-Glossary、Developer-Workflow 或对应运维说明。 - 不修改 `web/`、`android/`、共享 Agent API 和现有表结构。 ## 已确认覆盖与转换规则 ### PDD 商品 - 业务键:`goods_id`。 - URL 中的 goods_id 必须和字段一致;无效或不一致时跳过并报告。 - `title`、`shop_name`、URL 和可转换规格以来源覆盖本机。 - 旧 `skus_json` 转为 GoAuto 通用 `specs_json`:按维度顺序聚合唯一规格值;角色为 color/size/other;可选择状态取该值是否存在任一可用组合。 - 颜色价格只在同一颜色的所有有效非空价格唯一时写入;出现多个不同价格时价格留空、商品保持 `pending` 并报告,禁止猜最低或最高价。 - 来源 `collected` 且规格转换无冲突时目标状态为 `active`;其余为 `pending`。来源软删除记录默认跳过。 - 来源没有的销量、评价数量保持目标 `NULL`;覆盖现有记录时清为 `NULL`,体现“来源覆盖”。 - 人工停用的本机 PDD 商品不得被导入自动启用:目标原状态为 `disabled` 时保留 `disabled`。 ### 蝦皮商品 - 业务键:来源 `goods_id` → 目标 `shopee_item_id`。 - 标题、店铺、图片和规格以来源覆盖本机;参考售价来源不存在时清为 `NULL`,币种使用 GoAuto 系统配置,缺省 TWD。 - 聚合来源 `shopee_skus` 的唯一颜色/尺码:解析成功字段写入对应维度;`is_manual=1` 标为 manual,其他标为 import;解析失败或空字段不猜测并报告。 - 来源当前 `pdd_goods_id` 通过目标 `pdd_product.goods_id` 换算为数字 `pdd_product_id`;来源为空时清除本机关联,来源目标无效/缺失时本条标为冲突且不静默关联。 - 来源软删除蝦皮商品默认跳过;目标同 item ID 的存活记录覆盖。目标只有软删除记录时不自动恢复,报告冲突,避免绕过恢复语义。 ## 安全和事务 - 来源连接只允许 MySQL 且使用只读账号;密码不接受命令行参数,不输出 DSN。 - 来源配置从独立未跟踪配置或环境变量读取;目标读取 GoAuto `config.yaml` / 安全环境配置。 - dry-run 是默认模式且不写两边数据库。 - apply 开始前再次校验来源/目标 schema;来源使用一致性只读事务,目标使用单个事务。 - 写入后在提交前校验唯一键、关联完整性、JSON 和逐类计数守恒;失败整体回滚。 - 报告只含商品业务 ID、动作和非敏感原因,不含凭据、个人信息、原始响应、控件树或截图。 - 真正 apply 属于覆盖本地数据的高风险动作,必须在 dry-run 后再次等待用户确认。 ## 验收标准 - [ ] 默认运行不写数据库,输出稳定 dry-run 汇总和逐条冲突。 - [ ] 来源/目标 schema 不满足要求时在写入前明确失败。 - [ ] PDD 商品可以新增或按 goods_id 覆盖,且不产生重复。 - [ ] 蝦皮商品可以新增或按 shopee_item_id 覆盖,并正确换算 PDD 数字关联。 - [ ] PDD SKU 组合正确聚合为通用规格;同颜色多价格不猜测。 - [ ] 蝦皮 SKU 正确聚合颜色/尺码;无法解析的内容不猜测。 - [ ] 不导入旧规格映射、任务、订单、SYB 或其他范围外数据。 - [ ] 来源连接无写权限,目标 apply 单事务失败回滚。 - [ ] Go 单元测试、构建、项目 Server 验证、严格 harness 检查通过。 - [ ] 工单回写实现、真实测试、未验证项、提交哈希和文档 revision。 - [ ] dry-run 真实数量交给用户审核;未再次确认前不运行 apply。 ## 设计证据 无 Web/Android 页面变化,不需要 QuantUX/HTML。采用本工单中的数据映射、覆盖、事务和安全设计作为实施门禁。 ## 风险与回退 - 最大风险是把旧组合 SKU 误转成错误颜色价格或映射;通过唯一价格规则、旧映射不迁移和提交前校验控制。 - 来源和目标不支持分布式事务;先在来源只读快照完整装载,再开启目标单事务。 - apply 前应备份本地两张商品表;若后续需要回退,依据备份和导入报告另行确认执行,不在本命令自动删除数据。 ## 文档影响 需要更新 Wiki:记录离线导入入口、配置来源、dry-run/apply 命令、覆盖规则、非目标、安全边界和验证方式;再通过 harness 同步核心镜像。
Author
Owner

实施完成,等待 dry-run / apply 门禁确认

已提交并推送:

  • 166adc6 feat(#70): import cmautobuy product catalog
  • Wiki 归档:Task-70-从-cmautobuy-线上库导入-PDD-与蝦皮商品
  • 归档 revision:a37f18d06e86f6a4c4ac8a8e7c46d9b21e6b73b5

实现

  • 新增默认只读的 cmd/import-cmautobuy-products。
  • 来源使用 MySQL REPEATABLE READ 只读事务,目标 apply 使用单事务。
  • 同 goods_id / 存活 shopee_item_id 按用户确认覆盖;人工 disabled 保留。
  • PDD 组合 SKU 转通用规格,同颜色多价不猜测。
  • 蝦皮只聚合已解析颜色/尺码,旧 spec_mappings 不迁移。
  • 来源/目标配置均从未跟踪 YAML 读取;错误和报告不输出凭据或 DSN。
  • 无 Web、Android、API 或数据库 schema 变化。

真实 dry-run(未写数据库)

  • PDD 来源 8,459:新增 8,454,覆盖 3,冲突 2。
  • 蝦皮来源 25,151:新增 24,221,覆盖 925,冲突 5。
  • 可建立关联 20,796。
  • 同颜色多价格 0;未解析蝦皮 SKU 0。
  • 冲突:2 条 PDD URL/goods_id 无效或不一致;5 条蝦皮关联的来源 PDD 不存在、已删除或无法转换。
  • 计数守恒:PDD 8,454+3+2=8,459;蝦皮 24,221+925+5=25,151。

验证

  • go test ./app/goauto/cmautobuyimport ./cmd/import-cmautobuy-products:通过。
  • go test ./app/goauto/...:通过。
  • .\scripts\verify.ps1 -Component server:通过(全量 Go test + build)。
  • MySQL 8.4 隔离 *_test:dry-run 不写、覆盖、关联、提交前校验通过;测试库已删除。
  • python dev_scripts/harness.py check --strict:通过。
  • Wiki 四个核心页面已在线更新、回读并同步镜像,sync --check 通过。
  • 本机 gitea.env Token 失效导致 harness.py archive 返回 401;按 MCP 优先规则使用 Gitea MCP 创建并回读归档,未修改或输出 Token。

未执行

没有运行 --apply,没有覆盖 GoAuto 本地正式商品表。按照工单门禁,需用户查看上述精确影响后再次明确确认,且 apply 前先备份目标商品表。

## 实施完成,等待 dry-run / apply 门禁确认 已提交并推送: - `166adc6 feat(#70): import cmautobuy product catalog` - Wiki 归档:`Task-70-从-cmautobuy-线上库导入-PDD-与蝦皮商品` - 归档 revision:`a37f18d06e86f6a4c4ac8a8e7c46d9b21e6b73b5` ### 实现 - 新增默认只读的 `cmd/import-cmautobuy-products`。 - 来源使用 MySQL REPEATABLE READ 只读事务,目标 apply 使用单事务。 - 同 goods_id / 存活 shopee_item_id 按用户确认覆盖;人工 disabled 保留。 - PDD 组合 SKU 转通用规格,同颜色多价不猜测。 - 蝦皮只聚合已解析颜色/尺码,旧 spec_mappings 不迁移。 - 来源/目标配置均从未跟踪 YAML 读取;错误和报告不输出凭据或 DSN。 - 无 Web、Android、API 或数据库 schema 变化。 ### 真实 dry-run(未写数据库) - PDD 来源 8,459:新增 8,454,覆盖 3,冲突 2。 - 蝦皮来源 25,151:新增 24,221,覆盖 925,冲突 5。 - 可建立关联 20,796。 - 同颜色多价格 0;未解析蝦皮 SKU 0。 - 冲突:2 条 PDD URL/goods_id 无效或不一致;5 条蝦皮关联的来源 PDD 不存在、已删除或无法转换。 - 计数守恒:PDD 8,454+3+2=8,459;蝦皮 24,221+925+5=25,151。 ### 验证 - `go test ./app/goauto/cmautobuyimport ./cmd/import-cmautobuy-products`:通过。 - `go test ./app/goauto/...`:通过。 - `.\scripts\verify.ps1 -Component server`:通过(全量 Go test + build)。 - MySQL 8.4 隔离 `*_test`:dry-run 不写、覆盖、关联、提交前校验通过;测试库已删除。 - `python dev_scripts/harness.py check --strict`:通过。 - Wiki 四个核心页面已在线更新、回读并同步镜像,`sync --check` 通过。 - 本机 `gitea.env` Token 失效导致 `harness.py archive` 返回 401;按 MCP 优先规则使用 Gitea MCP 创建并回读归档,未修改或输出 Token。 ### 未执行 没有运行 `--apply`,没有覆盖 GoAuto 本地正式商品表。按照工单门禁,需用户查看上述精确影响后再次明确确认,且 apply 前先备份目标商品表。
Author
Owner

正式导入完成(2026-08-24)

用户已明确确认执行高风险 --apply。执行前已备份目标 pdd_product、shopee_product,来源 cmautobuy 线上库全程使用只读一致性事务,目标使用单事务提交。

正式写入结果

  • 导入前目标:PDD 3 条、有效蝦皮商品 987 条。
  • PDD:来源 8459;新增 8454、覆盖 3、冲突跳过 2。
  • 蝦皮:来源 25151;新增 24221、覆盖 925、关联冲突跳过 5。
  • 建立蝦皮→PDD 关联:20796。
  • 同颜色多价格:0;未解析蝦皮 SKU:0。
  • 未导入或修改任务、订单、SYB、设备、用户、规则、旧规格映射。

导入后核验

  • 目标总量:PDD 8457;有效蝦皮商品 25208;有效关联 20796。
  • 重复 goods_id:0;重复有效 shopee_item_id:0。
  • 非法 specs_json:0;悬空 PDD 关联:0。
  • 再次 dry-run:PDD 新增 0/覆盖 8457/冲突 2;蝦皮新增 0/覆盖 25146/冲突 5,幂等识别通过。

恢复与证据

  • 备份:D:\OPC\goauto-backups\cmautobuy-import-20260824-000239\goauto-products-before.sql
  • SHA-256:C30C6C52FF2094032BE7F1E03F7B4673C4F1A9AB01DD189958C42156E1BF41D9
  • 实现提交:166adc6fa84fc51457169426a1590a47a2b6f2b0
  • 状态镜像提交:1f2478a
  • Wiki 任务归档 revision:641d63aa97af4c512b10db4605561e31f1ef7825
  • Delivery Wiki revision:e0f06d2c6fd2a3d954e7c3a96cae966f977fb3a5
  • harness.py sync --check:通过。

工单保持待验收,不关闭。

## 正式导入完成(2026-08-24) 用户已明确确认执行高风险 `--apply`。执行前已备份目标 `pdd_product`、`shopee_product`,来源 cmautobuy 线上库全程使用只读一致性事务,目标使用单事务提交。 ### 正式写入结果 - 导入前目标:PDD 3 条、有效蝦皮商品 987 条。 - PDD:来源 8459;新增 8454、覆盖 3、冲突跳过 2。 - 蝦皮:来源 25151;新增 24221、覆盖 925、关联冲突跳过 5。 - 建立蝦皮→PDD 关联:20796。 - 同颜色多价格:0;未解析蝦皮 SKU:0。 - 未导入或修改任务、订单、SYB、设备、用户、规则、旧规格映射。 ### 导入后核验 - 目标总量:PDD 8457;有效蝦皮商品 25208;有效关联 20796。 - 重复 goods_id:0;重复有效 shopee_item_id:0。 - 非法 specs_json:0;悬空 PDD 关联:0。 - 再次 dry-run:PDD 新增 0/覆盖 8457/冲突 2;蝦皮新增 0/覆盖 25146/冲突 5,幂等识别通过。 ### 恢复与证据 - 备份:`D:\OPC\goauto-backups\cmautobuy-import-20260824-000239\goauto-products-before.sql` - SHA-256:`C30C6C52FF2094032BE7F1E03F7B4673C4F1A9AB01DD189958C42156E1BF41D9` - 实现提交:`166adc6fa84fc51457169426a1590a47a2b6f2b0` - 状态镜像提交:`1f2478a` - Wiki 任务归档 revision:`641d63aa97af4c512b10db4605561e31f1ef7825` - Delivery Wiki revision:`e0f06d2c6fd2a3d954e7c3a96cae966f977fb3a5` - `harness.py sync --check`:通过。 工单保持待验收,不关闭。
Author
Owner

用户验收通过

  • 用户于 2026-08-24 明确确认 #70 通过验收。
  • 正式导入、备份、完整性核验、幂等复跑及 7 条冲突跳过结果均纳入验收范围。
  • 任务归档 Wiki revision:fb055535a554a1ef9f30e27e6e6ee7cf3266091d
  • Delivery Wiki revision:e13b2092d60cec8bfa1a3dec21e858fdb9817ed5
  • 本地镜像提交:a439b0b
  • python dev_scripts/harness.py sync --check:通过。

按 DevHarness 流程关闭本单。

## 用户验收通过 - 用户于 2026-08-24 明确确认 #70 通过验收。 - 正式导入、备份、完整性核验、幂等复跑及 7 条冲突跳过结果均纳入验收范围。 - 任务归档 Wiki revision:`fb055535a554a1ef9f30e27e6e6ee7cf3266091d` - Delivery Wiki revision:`e13b2092d60cec8bfa1a3dec21e858fdb9817ed5` - 本地镜像提交:`a439b0b` - `python dev_scripts/harness.py sync --check`:通过。 按 DevHarness 流程关闭本单。
ila closed this issue 2026-08-24 09:11:20 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#70