feat(billing): 任务换额度定稿闭环——claim 凭据校验(40311)+ 定稿 4 任务目录

- claim_task_bonus 在幂等快捷路径前做完成凭据校验:report_feedback 查当日 rp_feedback、first_report 查 succeeded rp_report,无凭据 40311 且不打流水;sign_in/share_report 不校验(产品决策:签到行为即领取,分享内测期接受端侧自报,hard_cap 锁死刷量收益)
- task_bonus_rules 默认值与 .env.example 同步产品定稿(产品方案 §3.2,2026-09-11):sign_in 对话+10/day、report_feedback 发型+2/day、share_report 换装+3/day、first_report 重生成+1/lifetime;下架 invite_friend/profile_complete
- billing/repo 新增只读凭据探测 has_feedback_between/has_completed_report(import-linter 禁 billing→report,直查 shared.models 的 rp_* 表,永远只读)
- 测试:test_task_bonus_eligibility 5 用例(40311 两分支/凭据后 200/40910/40410/零流水)

偏差说明:test_task_bonus 与 test_task_bonus_rules 断言数值随定稿更新(发放/幂等/封顶语义未动);quota.py docstring「占位值」说法顺手更正。
This commit is contained in:
xsl
2026-09-12 00:23:43 +08:00
parent b9c3e4dada
commit 76a0502ea3
9 changed files with 365 additions and 44 deletions
+4 -2
View File
@@ -91,9 +91,11 @@ LLM_BUDGET_TIERS_JSON=[{"threshold":0.6,"name":"warn","blocked":[]},{"threshold"
REFRESH_TOKEN_TTL_SECONDS=2592000
# ── 任务奖励(FR-BILL-03/04)───────────────────────────────────────────────
# amount 均为占位值 1:正式数值待产品在产品方案 §3.2 定稿后改此处,不改代码。
# 产品方案 §3.2 定稿目录(2026-09-11):签到+10 对话/日、反馈+2 发型/日、
# 分享+3 换装/日、首次速测+1 重生成/终身。invite_friend/profile_complete 下架
# (无可信完成信号,不下发即下架,claim 返回 40410)。
# claim_period 决定幂等粒度(同一任务同周期只能领一次)。
TASK_BONUS_RULES_JSON={"sign_in":{"quota_key":"agent_chat","amount":1,"claim_period":"day"},"profile_complete":{"quota_key":"agent_chat","amount":1,"claim_period":"lifetime"},"report_feedback":{"quota_key":"report_regen","amount":1,"claim_period":"day"},"share_report":{"quota_key":"tryon","amount":1,"claim_period":"day"},"invite_friend":{"quota_key":"tryon","amount":1,"claim_period":"day"}}
TASK_BONUS_RULES_JSON={"sign_in":{"quota_key":"agent_chat","amount":10,"claim_period":"day"},"report_feedback":{"quota_key":"hairstyle","amount":2,"claim_period":"day"},"share_report":{"quota_key":"tryon","amount":3,"claim_period":"day"},"first_report":{"quota_key":"report_regen","amount":1,"claim_period":"lifetime"}}
# ── 客户端埋点(FR-SYS-06)─────────────────────────────────────────────────
EVENTS_MAX_BATCH=50