77 lines
4.3 KiB
Python
77 lines
4.3 KiB
Python
"""商品主表:对齐 Ozon ImportProductsV3 字段 + 本地扩展(raw/pricing/copy)。"""
|
||
from __future__ import annotations
|
||
|
||
import uuid
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import BigInteger, DateTime, Enum, Float, Integer, String, Text, Uuid, func
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from db import Base
|
||
from models.enums import Stage
|
||
from models.types import JSONType
|
||
|
||
|
||
class Product(Base):
|
||
__tablename__ = "products"
|
||
|
||
id: Mapped[uuid.UUID] = mapped_column(Uuid(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||
user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid(as_uuid=True), nullable=True)
|
||
shop_id: Mapped[uuid.UUID | None] = mapped_column(Uuid(as_uuid=True), nullable=True) # 上架店铺
|
||
stage: Mapped[Stage] = mapped_column(
|
||
Enum(Stage, native_enum=False, length=16), default=Stage.collected, index=True
|
||
)
|
||
|
||
# 采集溯源
|
||
source_platform: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||
source_item_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
|
||
source_url: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
|
||
# ── Ozon 字段(对齐 ImportProductsV3)──
|
||
offer_id: Mapped[str] = mapped_column(String(255), default="", index=True)
|
||
ozon_product_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, index=True)
|
||
ozon_sku: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
||
name: Mapped[str] = mapped_column(Text, default="")
|
||
description: Mapped[str] = mapped_column(Text, default="")
|
||
description_category_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
||
type_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
||
price: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
old_price: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
# 币种固定人民币(跨境卖家 CNY 计价);vat 恒为 0(简化税制,无 НДС),前端不再展示
|
||
currency_code: Mapped[str] = mapped_column(String(3), default="CNY", server_default="CNY")
|
||
vat: Mapped[str] = mapped_column(String(8), default="0", server_default="0")
|
||
depth: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
width: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
height: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
dimension_unit: Mapped[str] = mapped_column(String(4), default="mm", server_default="mm")
|
||
weight: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
weight_unit: Mapped[str] = mapped_column(String(4), default="g", server_default="g")
|
||
barcode: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||
|
||
# 图片(有序公网 URL,≤15)
|
||
images: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
primary_image: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
images360: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
color_image: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
pdf_list: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
promotions: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
|
||
# 动态属性(工作台映射后填)
|
||
attributes: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
complex_attributes: Mapped[list | None] = mapped_column(JSONType, nullable=True)
|
||
|
||
# ── 本地扩展(提交 Ozon 前剥离)──
|
||
raw: Mapped[dict | None] = mapped_column(JSONType, nullable=True) # 采集原文 + texts
|
||
pricing: Mapped[dict | None] = mapped_column(JSONType, nullable=True) # 计价结果
|
||
copy: Mapped[dict | None] = mapped_column(JSONType, nullable=True) # AI 文案结果
|
||
fx_rate: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
|
||
published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||
updated_at: Mapped[datetime] = mapped_column(
|
||
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), index=True
|
||
)
|
||
|
||
# 采集素材数量(冗余,供列表快速展示;由 service 维护)
|
||
asset_counts: Mapped[dict | None] = mapped_column(JSONType, nullable=True)
|