2ddea4159d
后台「领券数据」看板此前只有发起/完成数与耗时分位,缺少成功率视角。本 MR 补齐三档平台粒度成功率与一张按券(coupon_id)成功率表,并为看板增加领券状态多选过滤。 服务端埋点 领券每帧按 trace_id 把「成功平台」并集幂等写入 platform_success(merge_session_platform_success;读不到 session 行则静默跳过,不建兜底行;无新平台不写库)。 record_claims 按 session_app_env(trace_id) 反查并打 app_env 标。 新增平台推导:coupon_id_to_platform(前缀 mt_→美团 / tb_·ele_·elm_→淘宝 / jd_→京东,与客户端 couponIdToPlatform 同词表)、succeeded_platforms。成功语义统一为 success + already_claimed。 复用同一 SessionLocal、紧接 record_claims,不新增连接;fire-and-forget,异常已吞。 后台指标与接口 Summary 新增:②整单成功率(勾选平台全领到的 session 占发起数)、③点位成功率(Σ成功平台 / Σ勾选平台)、分平台点位成功率(恒含美团/淘宝/京东三档)。基数与「发起数」一致,含全部 session。 新端点 GET /coupon-data/coupons(coupon_slot_report):按券成功率表,数据源 coupon_claim_record,设备-天粒度,成功率 = 成功 /(成功+失败),skipped 排除,按尝试数倒序。 主表加 status 多选过滤(started/completed/failed/abandoned),汇总/成功率/趋势/明细整体按选中状态算,与 app_env 同级。 兼容性 / 风险 两个新列均可空、旧行按空集/不回填处理,无数据回填;埋点 fire-and-forget,失败不影响领券主流程。 部署务必 alembic upgrade head(因新增了 head 合并迁移)。 --------- Co-authored-by: guke <guke@autohome.com.cn> Reviewed-on: #130
38 lines
1.4 KiB
Python
38 lines
1.4 KiB
Python
"""coupon_session 加 platform_success 列(本次至少领到一张的平台 id 列表)
|
|
|
|
供 admin「领券数据」算 ②整单成功率 / ③点位成功率(平台粒度)。数据落点:服务端 /step 逐帧
|
|
按 trace_id 并集写入(见 app/repositories/coupon_state.merge_session_platform_success)。旧行 NULL
|
|
视作空集,已建表环境靠它补列、全新环境顺序应用不重复加列。设计:docs/guides/领券成功率指标-设计与埋点.md。
|
|
|
|
Revision ID: coupon_session_platform_success
|
|
Revises: admin_user_plain_password
|
|
Create Date: 2026-07-07 00:00:00.000000
|
|
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "coupon_session_platform_success"
|
|
down_revision: str | Sequence[str] | None = "admin_user_plain_password"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
# PG 用 JSONB,SQLite(本地/测试)退化为通用 JSON(同 model 的 _JSON variant / 建表迁移)。
|
|
_JSON = sa.JSON().with_variant(postgresql.JSONB(), "postgresql")
|
|
|
|
|
|
def upgrade() -> None:
|
|
with op.batch_alter_table("coupon_session", schema=None) as batch_op:
|
|
batch_op.add_column(sa.Column("platform_success", _JSON, nullable=True))
|
|
|
|
|
|
def downgrade() -> None:
|
|
with op.batch_alter_table("coupon_session", schema=None) as batch_op:
|
|
batch_op.drop_column("platform_success")
|