"""CPS 对账订单(cps_order)。 从联盟 API 按时间窗拉回、按平台落库的 CPS 订单明细。字段最初对齐美团 query_order, 后续兼容京东订单报表: 实测返回: - payPrice / profit 是「元」字符串 → 入库统一转「分」(与全站口径一致) - payTime / updateTime 是秒级时间戳 → 入库转 tz-aware datetime - status: 2付款 3完成 4取消 5风控 6结算(取消/风控不计佣金) order_id 全局唯一,reconcile 按它 upsert(订单状态会变,重复拉则更新)。京东订单用 `jd:` 前缀避免与美团订单号碰撞。 """ from __future__ import annotations from datetime import datetime from sqlalchemy import JSON, DateTime, Integer, String, func from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base class CpsOrder(Base): __tablename__ = "cps_order" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) # 平台:meituan / jd。历史数据迁移默认 meituan。 platform: Mapped[str] = mapped_column(String(20), default="meituan", index=True, nullable=False) # 平台订单号/行号包装后的全局唯一键,upsert 幂等。 order_id: Mapped[str] = mapped_column(String(64), unique=True, index=True, nullable=False) # 平台原始订单号/行号。京东一笔订单多 SKU 时可按行号区分。 external_order_id: Mapped[str | None] = mapped_column(String(128), index=True, nullable=True) external_row_id: Mapped[str | None] = mapped_column(String(128), index=True, nullable=True) # 渠道追踪位 = 群 sid(历史无 sid 订单为空)。按它归群聚合。 sid: Mapped[str | None] = mapped_column(String(64), index=True, nullable=True) act_id: Mapped[str | None] = mapped_column(String(64), index=True, nullable=True) biz_line: Mapped[int | None] = mapped_column(Integer, nullable=True) # 1=外卖 trade_type: Mapped[int | None] = mapped_column(Integer, nullable=True) # 1=cps 2=cpa pay_price_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) commission_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) # 预估佣金(profit) commission_rate: Mapped[str | None] = mapped_column(String(16), nullable=True) # "300"=3% "10"=0.1% refund_price_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) refund_profit_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) # 通用佣金拆分。美团只有预估 profit;京东有预估/实际佣金。 estimated_commission_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) actual_commission_cents: Mapped[int | None] = mapped_column(Integer, nullable=True) # 美团订单状态: 2付款 3完成 4取消 5风控 6结算 mt_status: Mapped[str | None] = mapped_column(String(8), index=True, nullable=True) # 京东订单有效码(validCode),用于判断是否有效/已完成。 jd_valid_code: Mapped[str | None] = mapped_column(String(16), index=True, nullable=True) invalid_reason: Mapped[str | None] = mapped_column(String(128), nullable=True) product_name: Mapped[str | None] = mapped_column(String(512), nullable=True) settle_month: Mapped[str | None] = mapped_column(String(16), nullable=True) site_id: Mapped[str | None] = mapped_column(String(128), nullable=True) position_id: Mapped[str | None] = mapped_column(String(128), nullable=True) pid: Mapped[str | None] = mapped_column(String(128), nullable=True) sub_union_id: Mapped[str | None] = mapped_column(String(128), nullable=True) pay_time: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), index=True, nullable=True ) mt_update_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) raw: Mapped[dict] = mapped_column( JSON().with_variant(JSONB(), "postgresql"), nullable=False, default=dict ) first_seen: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False ) def __repr__(self) -> str: # pragma: no cover return ( f"" )