feat: 支持无SKU目录导入策略 (#141)

This commit is contained in:
chengma
2026-08-11 11:03:18 +08:00
parent 6386d76488
commit 4259be0e55
17 changed files with 766 additions and 73 deletions
+9
View File
@@ -429,6 +429,15 @@ CREATE INDEX idx_syb_orders_list ON syb_orders(updated_at DESC, syb_id DESC);
仍存在于最新 `skus_json`。
- `shopee_sku_id` 只为兼容历史数据保留;顺运宝同步、弹窗、映射和建采购任务均不再读写它。
MySQL schema v8 将 `shopee_skus.sku_id` 保留为系统内部记录主键(兼容历史引用),
新增可空且唯一的 `shopee_sku_id` 保存真实外部 ID,并用唯一
`(goods_id, spec_key)` 标识无真实 ID 的规格。既有行将真实 ID复制到新列;新记录没有
真实 ID 时只生成内部主键,页面和接口不得把内部值冒充真实 SKU ID。`source` 和
`source_observed_at` 用于限制同来源更新,`is_manual=1` 始终优先保护。
`field_sources` 与 `field_observed_at` 是只含颜色、尺码、建议和 SKU 编码的 JSON
来源表;`fill_missing` 补字段时分别登记,`overwrite_same_source` 只更新来源属于本次
调用方且观测时间不旧的字段,避免不同脚本各补一部分后互相覆盖。
蝦皮详情把 `syb_orders` 按 `(shopee_goods_id, spec_key)` 聚合为“顺运宝观测规格”:
订单数按唯一 `syb_id` 行计数,累计数量求和,最近一行提供历史台币售价和图片。
该读模型不写入 `shopee_skus`。只有同一商品下恰好一条正式 SKU 的 `spec_raw`
+22 -3
View File
@@ -19,11 +19,12 @@ Token 通过 `CMAUTOBUY_CATALOG_TOKEN` 或未提交的 `config.yaml` 配置。
"schema_version": 1,
"batch_id": "source-file-20260811-001",
"observed_at": "2026-08-11T10:00:00+08:00",
"update_policy": "fill_missing",
"shopee_products": [
{"goods_id": "S-1", "title": "蝦皮上衣", "status": "NORMAL", "main_sku_code": "A01"}
],
"shopee_skus": [
{"sku_id": "SKU-1", "goods_id": "S-1", "spec_raw": "黑色,M", "color": "黑色", "size": "M", "parse_ok": true, "sku_code": "A01-B-M"}
{"sku_id": null, "goods_id": "S-1", "spec_raw": "黑色,M", "color": "黑色", "size": "M", "parse_ok": true, "sku_code": "A01-B-M"}
],
"pdd_products": [
{
@@ -42,16 +43,25 @@ Token 通过 `CMAUTOBUY_CATALOG_TOKEN` 或未提交的 `config.yaml` 配置。
金额单位固定为人民币分,不接受小数金额。`spec_raw` 必须原样提交。PDD 规格必须用
结构化 `dimensions` 和 `skus`,第三方不能提交数据库内部的 `skus_json`。
`sku_id` 是可选的真实蝦皮 SKU ID;来源文件没有该值时省略、传 `null` 或空字符串,
不得自行生成。系统用内部主键和 `goods_id + spec_key` 保持记录身份,后续取得真实 ID
会补到原记录,不会重复新增。
## 3. 写入与幂等规则
- 整个批次在一个事务中写入:实体、SKU、关联任一步失败就全部回滚。
- `(source, batch_id)` 是幂等键。请求字节相同则重放首次结果;同键不同内容返回 409。
- 较旧的 `observed_at` 不覆盖较新的接口数据。
- `update_policy` 可省略,默认 `fill_missing`:
- `insert_only`:只新增,已有规格不修改;
- `fill_missing`:只补颜色、尺码、建议、SKU 编码等空字段;
- `overwrite_same_source`:只有来源相同且 `observed_at` 更新时才覆盖来源字段。
- 较旧的 `observed_at` 不覆盖较新的接口数据,任何策略都不能覆盖 `is_manual=1`。
- `spec_raw` 和由它生成的规格身份不被更新;同商品同规格出现不同真实 SKU ID 返回 409。
- 蝦皮 upsert 不覆盖采购员维护的 PDD 链接;SKU 的 `is_manual` 不被接口改写。
- 空关联可以建立、相同关联不重复写;已有不同 PDD 关联返回 409,绝不静默替换。
- 批次缺少某条记录不表示删除,接口没有“全量覆盖”语义。
成功响应包含批次状态和各类新增、更新、关联计数。相同请求重放时
成功响应包含批次状态以及 SKU 新增、补空、同来源更新、人工跳过、旧数据跳过等计数。相同请求重放时
`replayed=true`。
## 4. 错误格式
@@ -70,3 +80,12 @@ Token 通过 `CMAUTOBUY_CATALOG_TOKEN` 或未提交的 `config.yaml` 配置。
调用方应按 `code` 处理,不要解析中文 `message`。校验错误通常是 400/422,业务冲突
是 409,临时服务错误是 500/503。响应和导入记录都不会回显 Token 或完整请求体。
## 5. schema v8 发布与回退
发布前先备份生产库,并在 MySQL 8.4、库名以 `_test` 结尾的测试库演练 v7→v8。
迁移只增加列和唯一索引,既有 `sku_id` 继续作为内部主键,因此历史引用不变;若检测
到同商品重复 `spec_key`,迁移会停止且不记录 v8,必须人工确认,不能自动合并。
旧版 Admin 不理解无真实 SKU ID 的新记录。应用回退前应暂停目录接口并确认没有此类
记录;不要删除 v8 列或把内部主键复制成伪造的外部 SKU ID。