Files
ozon-seller-kit/docs/v2.1/multi-sku-measurements.md

10 KiB
Raw Permalink Blame History

多 SKU 的实物规格与包装物流规格设计

状态:调研与设计结论,尚未实施。 关联:多 SKU 商品处理与试算页扩展方案。本文补充其“尺寸与重量”的双口径模型。 核心原则:每个 SKU 可以有独立的实物规格和包装物流规格;两者绝不混用。


1. 问题与结论

尺寸与重量有两种不同的业务口径:

口径 数据 用途
实物规格 商品本体长、宽、高、净重 商品规格展示、俄文文案、AI 尺寸标注图
包装物流规格 发货包装长、宽、高、含包装毛重 物流尺寸限制、物流费、价格试算、CSV 上品

同一个商品还可能有多个 SKU。容量、尺寸、套装数等 SKU 往往在两组数据上都不同;仅颜色不同的 SKU 则通常可继承父商品的两组默认值。

因此目标模型不是“商品加一张 SKU 价格表”,而是:

商品(SPU / 父记录)
├─ 共用:标题、描述、采购链接、图片、文案、计价默认值
├─ 默认实物规格:长宽高、净重
├─ 默认包装物流规格:长宽高、包装毛重
├─ SKU A:规格、两组规格覆盖、采购价、试算结果、货号
├─ SKU B:规格、两组规格覆盖、采购价、试算结果、货号
└─ SKU C:规格、两组规格覆盖、采购价、试算结果、货号

SKU 的某个值为空代表继承父商品默认值,不代表零。采集不到或来源未说明口径的“尺寸/重量”必须标记为待确认,不能猜测写入任意一组。

2. 当前实现风险

当前 /trial/:id 将 price、old_price、weight、depth/width/height、offer_id 放在单一 products 记录中:

  • TrialPricingPanel 使用重量尺寸做物流费和尺寸校验,且会回填商品价格;一个 SKU 会覆盖另一个 SKU。
  • AI 套图规划从采集参数表寻找“尺寸”,无法确认取到的是实物尺寸还是包装尺寸。
  • /api/materials 的 _apply_weight_dims 以“包装重量/重量”“包装长度/长度”等泛关键词解析,通用“产品尺寸”“重量”可能被当成物流规格。
  • 图片资产仅保存 variant_name,显示名能重复或改名,无法稳定绑定 SKU。
  • CSV 目前按商品一行导出,无法表达 SKU 的独立包装数据和报价。

因此不能只给当前价格卡增加输入框,必须先建立 SKU 与双规格的持久化模型。

3. 数据模型

3.1 命名、单位和继承

数据库统一使用 mm、g;前端用 cm、g 编辑。新功能不得再用裸 weight、depth、width、height 表达业务规格。

父商品和 product_variants 均使用相同、口径明确的字段:

字段组 字段 使用者
实物规格 physical_length_mm、physical_width_mm、physical_height_mm、net_weight_g 尺寸图、规格展示、文案
包装物流规格 package_length_mm、package_width_mm、package_height_mm、shipping_weight_g 试算、物流校验、导出
SKU 身份 source_variant_key、variant_name、specs 平台原始 SKU ID、展示规格、颜色/尺寸/容量
销售与计价 source_price、purchase_price、offer_id、barcode、logistics_level、pricing SKU 独立的输入、结果和上品标识
审计 measurements_meta、enabled、时间戳 来源、原始文本、确认状态、是否参与导出

measurements_meta 至少记录两组数据各自的 status(confirmed / ambiguous / missing)、来源、原始文本和更新时间。采集提供的数据不是人工确认的事实时,不应伪装为已确认。

SKU 的有效值按“SKU 覆盖 → 父商品默认值”逐字段合并。实物规格与包装物流规格独立继承:实物尺寸相同不代表包装尺寸也相同。

3.2 关联和旧字段

  • 新增持久化 product_variants 表,而不是长期把 SKU 数组放进 product.pricing JSON。
  • product_assets 增加可空 product_variant_id;现有 variant_name 仅保留展示兼容。
  • 父商品 pricing 只保存共享默认参数,如汇率、利润率、贴单费和默认物流等级;SKU pricing 保存输入快照、有效包装规格、计算结果和计算时间。
  • 当前 products.depth/width/height/weight 在迁移期间仅是兼容读写别名;双规格字段是新功能唯一事实来源。

4. 采集和后端接口

POST /api/materials 保持旧契约兼容,并新增可选 variants:

{
  "source": { "platform": "1688", "itemId": "...", "url": "..." },
  "variants": [
    {
      "source_variant_key": "平台原始 SKU ID",
      "variant_name": "白色 / 33 cm",
      "specs": { "颜色": "白色", "尺寸": "33 cm" },
      "source_price": 28.5,
      "physical_measurements": {
        "length_mm": 150, "width_mm": 150, "height_mm": 330, "net_weight_g": null,
        "status": "confirmed"
      },
      "package_measurements": {
        "length_mm": 180, "width_mm": 180, "height_mm": 380, "shipping_weight_g": 850,
        "status": "confirmed"
      },
      "image_url": "..."
    }
  ]
}

规则:

  • source_variant_key 优先使用来源平台稳定 ID;展示名不能作为幂等键。
  • 未采到的字段传 null;无法判断口径时保留原始参数、设 status: "ambiguous"。
  • 只有明确“包装/外箱/发货”口径的参数可写入包装物流规格;明确“商品/产品/本体”的参数可写入实物规格;泛称参数不自动落入任何组。
  • 服务端按来源 SKU ID 幂等更新,并把 SKU 图片关联至 product_variant_id。
  • SKU 使用独立接口,例如 GET/POST /api/products/{id}/variants、PATCH/DELETE /api/products/{id}/variants/{variant_id};不要用整份 ProductUpdate 承担 SKU 并发编辑。

服务端新增统一的 PricingService:前端可即时预览,但保存与导出时必须按“有效包装物流规格”重新计算,避免浏览器传入结果被篡改或前后端公式漂移。

5. 前端设计

页面拆成两个清晰区域:

  1. 商品规格与尺寸图:维护实物长宽高和净重;多 SKU 时可维护商品默认值,或为一个 SKU 覆盖。尺寸标注图唯一读取这里的已确认实物尺寸。
  2. 价格试算:维护包装长宽高、包装毛重、进货价、利润率、物流等级、贴单费、汇率;物流校验与价格结果只在此区域展示。

多 SKU 时,价格区使用明细表,列为“规格 / 实物规格摘要 / 包装规格摘要 / 进货价 / 销售价 / 状态”。点击一行打开抽屉或展开编辑器,而不是把八项字段强塞进表格:

实物规格(用于尺寸图)          包装物流规格(用于试算)
长 / 宽 / 高 / 净重              长 / 宽 / 高 / 包装毛重
状态:SKU 覆盖 / 继承 / 待确认    状态:SKU 覆盖 / 继承 / 待确认

交互约束:

  • 每个字段可以“恢复继承”;空值不是 0。
  • 修改父商品默认值只影响未覆盖字段;可以将某一组默认规格批量应用给选中的 SKU。
  • 包装物流规格缺失/无效时,该 SKU 不能试算和导出,但其他 SKU 不受影响。
  • 实物规格缺失时仍可试算/导出,但不能生成有数值的尺寸标注图。
  • 父商品列表不应任选一个 SKU 回写 product.price;应展示最低价、价格区间,或显式选择代表 SKU。

6. AI 尺寸图、导出与迁移

AI 尺寸图

尺寸标注图是实物信息,不是物流信息。规划器、提示词和任务上下文必须接收显式 physical_* 字段,不能从混合原始参数表兜底。

  • 多 SKU 实物尺寸不同:生成前必须选择 SKU;任务保存 product_variant_id 与实物规格快照。
  • 多 SKU 实物尺寸相同:可以使用父商品默认规格生成一张通用图。
  • 实物规格为 missing 或 ambiguous:规划器不安排尺寸图,也不能提交带数值的尺寸图任务。
  • 规格修改后,历史图依其快照标记为“基于旧规格生成”。

CSV 和上品

CSV 从“每商品一行”改为“每启用 SKU 一行”。进货价、包装毛重、包装尺寸和物流等级来自合并后的 SKU 有效值;实物尺寸绝不作为物流尺寸导出。导出前逐 SKU 校验货号、价格和包装物流规格,并列出失败原因。

每 SKU 一个 Ozon offer、只上代表 SKU、或未来平台变体合并,仍是待确认的商业策略;未确认前系统只生成可审阅的 SKU 级 CSV。

历史数据迁移

历史商品无 SKU 时视为一个隐式 SKU。把旧 pricing、weight、depth/width/height、offer_id 迁为默认 SKU 的包装物流规格,因为它们原本用于价格试算;实物规格一律为 missing,不得依据旧字段自动生成尺寸图。

7. 实施顺序与验收

阶段 内容 验收标准
0. 业务确认 明确 Ozon offer 策略、货号规则、尺寸图是否逐 SKU 生成 形成 CSV/上品规则
1. 数据和采集 SKU 表、父/SKU 双规格字段、迁移、variants 契约;收窄泛规格解析 未知口径不被伪造成实物或包装数据
2. 服务端计算 继承合并、统一计算/校验、SKU 级保存和查询接口 两 SKU、两组规格不相互覆盖
3. 试算页 实物规格区、包装物流试算区、SKU 表和编辑抽屉 刷新后继承、状态、价格和告警一致
4. 导出和图片 SKU 行 CSV;尺寸图上下文绑定 SKU 与实物快照 包装尺寸绝不进入尺寸图

至少覆盖:单 SKU 回归、多 SKU 不同价格、仅颜色不同继承两组规格、实物相同包装不同、包装相同实物不同、泛称规格待确认、一个 SKU 导出失败但其他可导出、尺寸图只使用实物规格、SKU 改名但稳定 ID 不变、历史商品迁移。

8. 待确认决策

  1. Ozon 中多 SKU 是否一律拆成独立 offer,还是要保留变体合并能力?
  2. 货号由父商品自动派生,还是必须人工逐 SKU 维护?
  3. 哪些采集来源的实物/包装字段可信,哪些只能作为待确认原始信息?
  4. 尺寸图是否必须逐 SKU 生成;AI 主图和场景图由谁指定代表 SKU?
  5. 父商品在采集箱中展示最低价、价格区间,还是代表 SKU 的价格?