feat(coupon-data): 领券数据看板加领券状态多选过滤
- coupon_data_report 加 statuses 参(status.in_ 过滤,与 app_env 同级),整视图联动 - 路由 /coupon-data 加多值 status 参(不传=全部);不影响 /coupons 按券表 - 新增 test_coupon_data_status_filter Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -127,6 +127,7 @@ def coupon_data_report(
|
||||
date_to: str,
|
||||
user: str | None = None,
|
||||
app_env: str | None = None,
|
||||
statuses: list[str] | None = None,
|
||||
granularity: str = "day",
|
||||
limit: int = 500,
|
||||
offset: int = 0,
|
||||
@@ -136,6 +137,8 @@ def coupon_data_report(
|
||||
|
||||
- user:手机号/昵称模糊搜(匹配不到任何用户 → 空结果)。
|
||||
- app_env:prod/dev 精确;None=全部。
|
||||
- statuses:领券状态多选(started/completed/failed/abandoned);None/空=全部。整个视图
|
||||
(汇总/成功率/趋势/明细)按选中状态算,与 app_env 同级过滤(方案 A)。
|
||||
- sort:time=发起时刻倒序(默认) / elapsed=全程耗时倒序(None 末尾)。
|
||||
"""
|
||||
by_hour = granularity == "hour"
|
||||
@@ -158,6 +161,8 @@ def coupon_data_report(
|
||||
)
|
||||
if app_env is not None:
|
||||
stmt = stmt.where(CouponSession.app_env == app_env)
|
||||
if statuses:
|
||||
stmt = stmt.where(CouponSession.status.in_(statuses))
|
||||
if user_ids is not None:
|
||||
stmt = stmt.where(CouponSession.user_id.in_(user_ids))
|
||||
rows = list(db.execute(stmt).scalars())
|
||||
|
||||
@@ -54,6 +54,10 @@ def get_coupon_data(
|
||||
date_to: Annotated[str | None, Query(description="结束日 北京 YYYY-MM-DD,闭区间,默认=date_from")] = None,
|
||||
user: Annotated[str | None, Query(description="用户手机号/昵称模糊搜;不传=全部")] = None,
|
||||
app_env: Annotated[str, Query(description="prod(默认) / dev / all(全部环境)")] = "prod",
|
||||
status: Annotated[
|
||||
list[str] | None,
|
||||
Query(description="领券状态多选 started/completed/failed/abandoned;不传=全部"),
|
||||
] = None,
|
||||
granularity: Annotated[
|
||||
str, Query(description="day=按天 / hour=按小时(北京);区间>1 天建议 day")
|
||||
] = "day",
|
||||
@@ -75,7 +79,7 @@ def get_coupon_data(
|
||||
env = None if app_env == "all" else app_env
|
||||
result = coupon_data.coupon_data_report(
|
||||
db, date_from=d_from.isoformat(), date_to=d_to.isoformat(),
|
||||
user=user, app_env=env, granularity=granularity,
|
||||
user=user, app_env=env, statuses=status, granularity=granularity,
|
||||
limit=limit, offset=offset, sort=sort,
|
||||
)
|
||||
return CouponDataOut(
|
||||
|
||||
@@ -270,3 +270,30 @@ def test_step_writes_platform_success_to_session(client) -> None:
|
||||
db.commit()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_coupon_data_status_filter() -> None:
|
||||
"""状态多选过滤(方案 A):整个视图按选中状态算;None/空=全部。"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
db.add_all([
|
||||
_agg_session("st-A", ["meituan-waimai"], ["meituan-waimai"], status="completed"),
|
||||
_agg_session("st-B", ["meituan-waimai"], ["meituan-waimai"], status="started"),
|
||||
_agg_session("st-C", ["meituan-waimai"], None, status="failed"),
|
||||
_agg_session("st-D", ["meituan-waimai"], ["meituan-waimai"], status="abandoned"),
|
||||
])
|
||||
db.flush()
|
||||
base = dict(date_from="2020-01-02", date_to="2020-01-02", app_env="prod")
|
||||
# None = 全部 4 发起
|
||||
assert coupon_data_report(db, **base)["summary"]["started_count"] == 4
|
||||
# 排除 started → 3 发起(整个视图,发起数也随之变)
|
||||
sub = coupon_data_report(db, **base, statuses=["completed", "failed", "abandoned"])["summary"]
|
||||
assert sub["started_count"] == 3
|
||||
assert sub["completed_count"] == 1
|
||||
# 只 completed → 发起数=1、整单成功率基数=1(该 completed 是整单成功)
|
||||
comp = coupon_data_report(db, **base, statuses=["completed"])["summary"]
|
||||
assert comp["started_count"] == 1
|
||||
assert comp["full_success_rate"] == 1.0
|
||||
finally:
|
||||
db.rollback()
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user