"""领券今日状态端点的收发模型。""" from __future__ import annotations from pydantic import BaseModel class CouponPromptDismissIn(BaseModel): """客户端拒绝/关闭领券引导窗的通知体。 server 据此记一条今日 engagement(dismissed)→ 今天**这个 App** 不再弹引导窗。 频控按 (device, package, 日):各 App 独立。package 缺省 ""(老客户端兼容,退化为全局态)。 MVP 不鉴权,按 device_id 判断;user_id 登录态带上就一并记(资产),可空。 """ device_id: str package: str = "" user_id: int | None = None class CouponPromptShownIn(BaseModel): """客户端弹出领券引导窗即上报(记 shown)。 弹出那刻就记一条今日 engagement(shown)→ 今天**这个 App** 不再自动弹(频控主判据, 管跨重装;本地 SP 兜后台抖动)。后续用户点领取/拒绝再把 type 升级成 claim_started/dismissed。 """ device_id: str package: str user_id: int | None = None class CouponPromptShouldShowOut(BaseModel): """切到外卖 App 时是否还应弹领券引导窗。今天**这个 App** 已 engage(弹/领/拒)过 → false。""" should_show: bool class CouponCompletedTodayOut(BaseModel): """这台设备今天是否已跑完整轮领券(到 done 帧)。完成 → 首页「去领取」卡置灰。""" completed: bool class CouponStatsOut(BaseModel): """「我的」页战绩卡「领取优惠券 X 张」数据源:该登录用户累计领到的券数。 口径(2026-06-15 用户定):SUM(claimed_count) —— 各成功领券记录的 pricebot 展示张数之和, 与领券完成时给用户看的「本次领了 N 张」同源。详见 repositories.coupon_state.sum_claimed_count。 """ coupon_count: int class CouponSessionIn(BaseModel): """客户端领券流水上报体(admin「领券数据」看板数据源,POST /api/v1/coupon/session)。 一次领券两段上报,按 trace_id upsert 到 coupon_session: - 发起(status=started):带勾选平台 + 机型/ROM/app_env + started_at_ms(发起墙钟毫秒)。 - 收尾(completed/failed/abandoned):带 elapsed_ms(全程耗时)+ platform_elapsed(各平台耗时)+ claimed_count。 不鉴权(同领券循环 MVP,按 device_id/trace_id),user_id 登录态带上做留痕(可空)。 """ trace_id: str device_id: str status: str # started / completed / failed / abandoned started_at_ms: int # 发起墙钟毫秒(客户端 System.currentTimeMillis) user_id: int | None = None platforms: list[str] | None = None origin_package: str | None = None device_model: str | None = None rom: str | None = None app_env: str | None = None elapsed_ms: int | None = None platform_elapsed: dict[str, int] | None = None claimed_count: int | None = None trace_url: str | None = None