Files
atlas-seller-kit/docs/product/data-model.md
T
2026-09-23 17:18:09 +08:00

51 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 商品与 SKU 数据模型
> 目标数据库:PostgreSQL。单位统一存储为毫米(`mm`)和克(`g`)。所有租户数据必须拥有或可追溯至 `workspace_id`。
## 1. 云端租户层
```text
users ── workspace_memberships ── workspaces
└─ stores ── platform_connections
```
`stores` 只保存其唯一绑定的平台标识、店铺默认计价币种和连接状态;一个门店不能跨平台使用。市场/国家、默认语言、可用语言和可用币种属于平台能力配置,不能从门店推导。敏感凭据经加密后保存在专用连接密钥记录中,绝不放进前端、日志或商品 JSON。
商品编辑、定价和佣金规则中的 `market_code` 是当前**平台业务上下文**的一部分:首期 Ozon 使用平台默认市场 `RU`;未来平台支持多市场时,由顶部全局上下文选择或使用平台默认值,而非读取门店字段。
## 2. 商品领域
```text
workspaces 1 ── N collection_items ── 0..1 products (SPU) 1 ── N product_variants (SKU)
│ │
└─ N product_platform_profiles ── N product_variant_platform_listings
(平台发布配置) (平台 SKU 首次发布映射)
```
`collection_items` 是工作空间级采集箱记录,保存来源平台、来源商品键、原始证据、规范化结果、素材任务和可空的草稿商品关联;它在采集阶段没有 `target_platform_id` 或 `target_store_id`。每个父商品至少有一条 SKU。`products` 仅是**采集箱商品**的跨平台可复用资料:来源标题、用户手填或主动 AI 填报的型号、条形码、采买地址、货源备注、默认规格和来源证据;采集入箱时型号允许为空,不直接从来源数据猜测填入。首次上架前型号必须非空并通过现有校验;不把任何一个平台的类目、价格、属性或上架状态直接写到该表。
`product_platform_profiles` 是 `product_id + platform_id` 唯一的平台发布配置。用户在页头选中平台并进入编辑时才创建或读取它;它保存当前目标门店、该平台的标题/简介/标签、类目和类型、平台通用属性及本平台草稿版本。A 平台与 B 平台独立配置、独立状态;A 已上架不会让 B 显示已上架。门店只是配置中可改的当前发布目标,实际每次发布仍会在 SKU 映射中固化当时的 `store_id`。
`product_variants` 保存:稳定来源键、展示名、删除状态、排序、采购价、SKU 规格、包装物流规格、实物规格和时间戳。`product_variant_platform_listings` 保存平台 SKU 维度的数据:`profile_id`、`variant_id`、用户填写或主动 AI 填报生成的本平台 `offer_id`(货号)、售价、划线价、币种、平台变体属性、首次导入状态/失败原因、首次导入任务和当时 `store_id`、Ozon `product_id`。AI 填报落地时新增可空的 SKU 发布标题 `title`;`title=null`、`description=null`、`tags=[]` 分别继承 SPU 当前平台发布配置的标题、描述、标签,非空/非空数组则按 SKU 覆盖。`product_variants.display_name` 只是内部展示名,不能充当发布标题。中俄文案对照按 SPU/SKU 作用域保存,继承时读取 SPU 对照而不复制。采集入箱时不填入 `offer_id`;编辑页主动生成或手填后,它对同一门店/平台连接必须唯一,并且是首次上架的必填项。成功导入的 SKU 映射不可再次创建导入任务;删除 Atlas SKU 只软删 Atlas 关联,不删除平台商品和审计记录。
`platform_listings`(实际建表名待定)保存店铺级在线商品 SKU 镜像,一条记录对应 Ozon 的一个 `product_id` / `offer_id`,而非采集箱 SPU:`store_id`、平台 `product_id`、`offer_id`、平台 SKU、名称、价格、可见性、审核/错误、库存、图片摘要、完整同步快照、最近同步时间和来源(`atlas_published` / `external_sync`)。它是**平台 + 门店独有**的外部事实记录,绝不跨平台、跨门店复用,也不因关联了采集箱 SKU 就变成采集箱商品。它由异步同步任务更新,包含非 Atlas 发布的商品;通过 `store_id + offer_id/product_id` 可选关联 Atlas SKU。采集箱不因成功上架而删除,其当前平台状态由首次导入映射汇总;在线商品的 `visible` 只用于在线商品实际可见性展示。
## 3. 双规格和继承
父商品可提供默认的实物/包装规格;SKU 可以逐字段覆盖:
- 实物:`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 覆盖 → 父商品默认”合并;两组规格独立合并。`null` 表示该字段继承,不是零,也不是 SKU 不存在。每组须有来源、原始文本、状态(`confirmed`/`ambiguous`/`missing`)和确认时间;口径未知的数据不能落入任一规格组。
## 4. 动态属性和媒体
`product_attributes` 使用结构化行保存 `profile_id`、可空 `variant_id`、本地 key、平台属性 ID、复杂属性 ID、JSON 值、语言、来源与确认状态。平台 schema 驱动类型、必填、字典、多值和 `is_aspect`;`is_aspect=true` 默认 variant scope,但允许业务覆盖。AI 类目推荐保存为独立候选记录,包含输入证据摘要、候选类目、置信度、依据、模型版本、用户确认结果和时间,不可直接覆盖人工选择。
`product_assets`(落地时复用基础表 `media_assets` 或以其为资产事实来源)保存 `storage_provider`、`bucket`、`object_key`、内容哈希、MIME 类型、尺寸和归属关系;不保存长期有效或公开的对象存储 URL。`variant_media` 首期只保存 SKU 对图片资产稳定 ID 的选择、原图/水印派生图关系与顺序;视频相关字段可为未来预留但不在首期 UI 或发布请求中启用。资产归属一律用稳定 ID;采集平台无法稳定给 SKU 归属时,只作为商品级候选池。来源页面图片 URL 仅保存在采集证据中;前端预览/下载 URL 由服务端按 `object_key` 临时签发。
## 5. 定价、任务和发布
`variant_pricing_snapshots` 保存确认时的输入、合并后的包装规格、公式版本、汇率、结果、告警和时间;报价快照还应关联 `profile_id`,因为货币和店铺定价方案属于平台发布配置。导出/发布时服务端重新校验,不能信任浏览器结果。所有 AI、媒体、导出和发布任务保存 `workspace_id`、`product_id`、可空/必填的 `profile_id` 与 `variant_id`,可重试、可恢复并隔离租户。