"""admin CPS 分发与对账 schemas。金额统一「分」(cents),前端 yuan() 展示。 平台:meituan(actId+sid 转链对账) / taobao(淘口令,只统计点击) / jd(链接,只统计点击)。 对账类字段对淘宝/京东为 None → 前端显示 "-"(无法对账)。 """ from __future__ import annotations from datetime import datetime from pydantic import BaseModel, ConfigDict, Field # ───────────── 群 ───────────── class CpsGroupOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int sid: str | None = None # 仅美团群有 name: str platforms: list[str] = Field(default_factory=list) member_count: int | None = None status: str remark: str | None = None created_at: datetime class CpsGroupCreate(BaseModel): name: str = Field(min_length=1, max_length=128) # 该群发哪些平台,至少选一个 platforms: list[str] = Field(min_length=1) # 仅当含 meituan 时需要(留空自动生成);纯淘宝/京东不填,后端置 None。 sid: str | None = Field(default=None, max_length=64, pattern=r"^[A-Za-z0-9]+$") member_count: int | None = Field(default=None, ge=0) remark: str | None = Field(default=None, max_length=256) class CpsGroupUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=128) platforms: list[str] | None = None member_count: int | None = Field(default=None, ge=0) status: str | None = Field(default=None, pattern=r"^(active|archived)$") remark: str | None = Field(default=None, max_length=256) # ───────────── 活动 ───────────── class CpsActivityOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int platform: str name: str act_id: str | None = None product_view_sign: str | None = None payload: str | None = None # 淘宝淘口令 / 京东链接 status: str remark: str | None = None created_at: datetime class CpsActivityCreate(BaseModel): name: str = Field(min_length=1, max_length=128) platform: str = Field(pattern=r"^(meituan|taobao|jd)$") # 美团:act_id 或 product_view_sign 二选一 act_id: str | None = Field(default=None, max_length=64) product_view_sign: str | None = Field(default=None, max_length=128) # 淘宝:整段淘口令文本 / 京东:推广链接 payload: str | None = Field(default=None, max_length=4096) remark: str | None = Field(default=None, max_length=256) # ───────────── 生成链接(批量) ───────────── class CpsReferralLinksRequest(BaseModel): group_id: int activity_ids: list[int] = Field(min_length=1) class CpsReferralLinkItem(BaseModel): activity_id: int activity_name: str platform: str redirect_url: str # 我们的落地页 /c/{code}(发群用) code: str class CpsReferralLinksOut(BaseModel): group_name: str results: list[CpsReferralLinkItem] # ───────────── 对账拉单 ───────────── class CpsReconcileResult(BaseModel): fetched: int inserted: int updated: int pages: int # ───────────── 订单明细 ───────────── class CpsOrderOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int order_id: str sid: str | None = None act_id: str | None = None pay_price_cents: int | None = None commission_cents: int | None = None commission_rate: str | None = None mt_status: str | None = None invalid_reason: str | None = None product_name: str | None = None pay_time: datetime | None = None # ───────────── 统计 ───────────── class CpsGroupStat(BaseModel): group_id: int | None = None sid: str | None = None name: str platforms: list[str] = Field(default_factory=list) member_count: int | None = None click_pv: int = 0 click_uv: int = 0 copy_pv: int = 0 # 淘宝"复制口令"次数 copy_uv: int = 0 # 对账类:淘宝/京东无法对账 → None(前端显示 "-");美团群为数值 order_count: int | None = None settled_count: int | None = None canceled_count: int | None = None gmv_cents: int | None = None est_commission_cents: int | None = None settled_commission_cents: int | None = None class CpsStatsOut(BaseModel): groups: list[CpsGroupStat] total_order_count: int total_est_commission_cents: int total_settled_commission_cents: int