d55f47fc59
- model: cps_activity.image_url + 迁移 cps_activity_image 回填存量淘宝活动为现有图 - admin: 新建淘宝活动必传图(上传 /upload-image 或选已有 /activity-images),存绝对 URL - 落地页 cps_redirect: 按 link→activity 取图展示,缺图兜底默认图,img src 经 html.escape - media: save_cps_image + to_abs_media_url(基于 CPS_REDIRECT_BASE,跨域 admin-web 可显示) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
143 lines
4.8 KiB
Python
143 lines
4.8 KiB
Python
"""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 # 淘宝淘口令 / 京东链接
|
|
image_url: str | None = None # 淘宝落地页图(绝对 URL)
|
|
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)
|
|
# 淘宝落地页图(绝对/相对 URL;淘宝必填,由 router 校验)
|
|
image_url: str | None = Field(default=None, max_length=512)
|
|
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
|