Files
shaguabijia-app-server/app/repositories/ad_ecpm.py
T
ouzhou da7ce69494 feat(ad): eCPM 上报接口 + 冷却策略解耦纯函数 + savings JSONB 跨库修复 (#8)
- 新增 POST /api/v1/ad/ecpm-report:激励视频展示后客户端上报本次 eCPM,落 ad_ecpm_record 做内部收益统计(model/repository/schema/alembic 迁移 + 接口文档)
- 看广告冷却策略抽到 app/core/ad_cooldown.py 纯函数;ad_reward.today_status 只取数据,换策略只改这一处
- savings.dishes 改 JSON().with_variant(JSONB,"postgresql"):SQLite 无 visit_JSONB 会让 create_all 编译崩,修复后测试套件恢复

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: OuYingJun1024 <1034284404@qq.com>
Reviewed-on: #8
Co-authored-by: ouzhou <ouzhou@wonderable.ai>
Co-committed-by: ouzhou <ouzhou@wonderable.ai>
2026-06-01 22:23:15 +08:00

50 lines
1.4 KiB
Python

"""广告 eCPM 上报 CRUD(内部收益统计/对账)。
客户端在广告展示后(onAdShow)读到 eCPM,经鉴权接口上报,这里落库。鉴权接口已确保
user 存在(JWT),故不做 UnknownUser 校验。best-effort 上报:丢一两条不影响业务,
穿山甲后台报表是结算权威兜底。
"""
from __future__ import annotations
from sqlalchemy import func, select
from sqlalchemy.orm import Session
from app.core.rewards import cn_today
from app.models.ad_ecpm import AdEcpmRecord
def create_ecpm_record(
db: Session,
user_id: int,
*,
ad_type: str,
ecpm_raw: str,
adn: str | None = None,
slot_id: str | None = None,
) -> AdEcpmRecord:
"""落一条 eCPM 上报记录。report_date 用北京时间当天,供按天聚合。"""
rec = AdEcpmRecord(
user_id=user_id,
ad_type=ad_type,
adn=adn,
slot_id=slot_id,
ecpm_raw=ecpm_raw,
report_date=cn_today().isoformat(),
)
db.add(rec)
db.commit()
db.refresh(rec)
return rec
def count_today(db: Session, user_id: int) -> int:
"""该用户今日(北京时间)上报的 eCPM 条数,排查/对账辅助用。"""
return db.execute(
select(func.count())
.select_from(AdEcpmRecord)
.where(
AdEcpmRecord.user_id == user_id,
AdEcpmRecord.report_date == cn_today().isoformat(),
)
).scalar_one()