6.7 KiB
V2.2 数据库与领域模型
状态:设计,尚未创建迁移。数据库单位统一为
mm与g。
1. 模型边界
products(父商品 / SPU) 1 ─── N product_variants(可售 SKU / Ozon offer)
│ │
├── product_attributes ├── product_variant_media ── product_assets
├── product_assets(候选池) ├── product_attributes(scope=variant)
└── product_pricing_defaults └── variant_pricing_snapshots
保留现有 products 主键和采集来源字段,以便采集箱和历史链接继续有效;其单 SKU 价格、尺寸、offer_id 字段只作为迁移兼容层,V2.2 写路径不再以它们为事实来源。每个父商品至少有一条 product_variants 记录:单规格商品拥有默认 SKU,多规格商品拥有多个 SKU;两者不采用不同的数据结构。
2. 父商品 products
新增/规范的核心字段:
| 字段 | 说明 |
|---|---|
model_code |
通用型号,所有 SKU 共用;可由 AI 建议,用户可编辑。 |
title_zh、name、description |
中文标题、俄文标题、俄文简介。 |
rich_content |
已验证的 JSON 富内容。 |
barcode |
当前按业务决策作为通用字段。发布阶段若 Ozon/业务要求 SKU 级条码,再增加显式覆盖字段,不从图片或名称推断。 |
purchase_url、supply_note |
采买地址和货源备注。 |
description_category_id、type_id |
Ozon 类目和商品类型。 |
pricing_defaults |
默认利润率、贴单费、物流等级、划线价倍数、汇率等可继承计价参数。 |
package_*_default |
默认包装物流规格;只作为 SKU 的可继承默认值。 |
physical_*_default |
默认实物规格;只作为 SKU 的可继承默认值。 |
历史 raw 继续存原始采集文本/参数,绝不可将口径不明的原始“尺寸/重量”自动写入新规格字段。
3. SKU product_variants
| 字段组 | 字段 | 说明 |
|---|---|---|
| 身份 | id、product_id、source_variant_key、variant_name、specs、sort_order、enabled |
source_variant_key 与来源平台联合唯一;显示名称可以变化或重复。 |
| 销售 | offer_id、purchase_price、selling_price、old_price、currency_code |
offer_id 对启用 SKU 必须唯一;售价和划线价仅由定价确认或人工编辑写入。 |
| 包装物流 | package_length_mm、package_width_mm、package_height_mm、shipping_weight_g、package_measurements_meta |
用于试算、物流校验和 Ozon import。null 表示继承,不表示零。 |
| 实物 | physical_length_mm、physical_width_mm、physical_height_mm、net_weight_g、physical_measurements_meta |
用于尺寸图、规格展示、文案,绝不用于物流计算。 |
| 发布 | ozon_product_id、ozon_sku、publish_state、published_at |
为一 SKU 一 offer 的后续同步预留。 |
| 审计 | created_at、updated_at、deleted_at |
SKU 采用软删除,防止丢失历史报价与外部映射。 |
两组 *_measurements_meta 至少存每个字段/字段组的 status(confirmed、ambiguous、missing)、来源、原始文本、确认时间。有效值按“SKU 覆盖 → 父商品默认值”逐字段合并;两组规格独立合并。这里的 null 仅表示某个可继承字段未覆盖父商品默认值;绝不表示 SKU 记录不存在,也不以此判断商品是否为单规格。
4. 动态属性 product_attributes
类目不同且将来可能持续增加属性,不能靠不断扩展 products 列。使用结构化属性表:
| 字段 | 说明 |
|---|---|
id、product_id、product_variant_id |
通用属性只填 product_id;SKU 属性还填所属 product_variant_id。 |
scope |
common 或 variant;数据库约束与两个外键一致。 |
attribute_key、attribute_name |
本地稳定键和最近一次展示名称。 |
ozon_attribute_id、complex_id |
已映射时记录 Ozon 属性身份。 |
values |
JSON 数组,保存文本与可选 dictionary_value_id,能表达单值、多值、数值与布尔。 |
source、status |
collected/ai/manual 与 confirmed/ambiguous/missing。 |
动态属性 schema 来自 Ozon:先由父商品的 description_category_id + type_id 调用 /v1/description-category/attribute,再按返回的 id、type、is_required、is_collection、max_value_count、dictionary_id 和 is_aspect 渲染与校验。dictionary_id > 0 时,值通过属性值字典/搜索接口确认 dictionary_value_id 后保存。
通用属性包括品牌、型号、主题标签及默认的类目共有属性。变体属性包括颜色、颜色名称以及 Ozon schema 标记 is_aspect=true 的所有属性;is_aspect 是默认归属,不是硬编码限制。用户或采集规则可把某个非 is_aspect 属性(例如按容量销售的商品的容量)标记为 variant scope,并为每个 SKU 保存不同值。specs 仅是来源规格的原始/展示快照,不能替代已确认的属性值。
5. 素材与媒体选择
product_assets 保存一次资产事实:product_id、可空 product_variant_id、media_type(image/video)、source_group(collected_main/collected_sku/collected_detail/generated/upload)、原始/当前 URL、尺寸、生成任务/规格快照及来源信息。若采集平台无法稳定给出 SKU 归属,product_variant_id 必须为 null。
新增 product_variant_media 表保存每个 SKU 的已选媒体,而不是复制资产:product_variant_id、asset_id、role(image/video/video_cover)、sort_order、selected_at。同一商品级素材可安全地被多个 SKU 选用;同一 SKU 的排序独立。发布时仅取该 SKU 已选图片,并执行 Ozon 的图片数量、HTTPS 可访问性等校验。
6. 定价快照
variant_pricing_snapshots 记录不可变的确认结果:SKU、输入参数、合并后的包装物流规格、公式版本、结果、告警、汇率、calculated_at、确认人/来源。SKU 表可缓存最新快照 ID 以加速展示;导出或上架时服务端必须以有效包装规格重新校验,不能信任浏览器传回的价格结果。
7. 迁移原则
- 每个历史
products记录创建一个默认 SKU,复制原offer_id、价格和pricing。 - 历史
weight/depth/width/height迁入默认 SKU 的包装物流规格,因为旧字段只服务于试算;实物规格标记missing。 - 历史素材先保留为商品级候选素材;不根据
variant_name倒推 SKU 绑定。 - 新读路径优先
product_variants;在迁移完成前,旧字段只读兼容,禁止双向覆盖。