docs(welfare): 15天不活跃清零金币/现金 设计文档(spec) (#144)
修改INACTIVITY_RESET_ENABLED语义,为false时清空金币操作只记录审计日志,不执行操作。 --------- Co-authored-by: guke <guke@autohome.com.cn> Reviewed-on: #144
This commit was merged in pull request #144.
This commit is contained in:
@@ -302,11 +302,35 @@ def test_run_once_warns_then_resets() -> None:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_worker_disabled_returns_none(monkeypatch) -> None:
|
||||
def test_worker_run_once_entry_dry_run(monkeypatch) -> None:
|
||||
"""ENABLED=false(默认语义)→ worker 常驻但只记审计不清(dry_run = not ENABLED)。"""
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.core import inactivity_reset_worker as w
|
||||
from app.core.config import settings
|
||||
monkeypatch.setattr(settings, "INACTIVITY_RESET_ENABLED", False)
|
||||
assert w.start_inactivity_reset_worker() is None
|
||||
from app.models.wallet import CoinAccount
|
||||
|
||||
monkeypatch.setattr(settings, "INACTIVITY_RESET_ENABLED", False) # false = 只记审计
|
||||
monkeypatch.setattr(settings, "INACTIVITY_RESET_DAYS", 15)
|
||||
monkeypatch.setattr(settings, "INACTIVITY_WARN_DAYS_BEFORE", "")
|
||||
monkeypatch.setattr(w, "_cn_today", lambda: date(2026, 2, 1))
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
uid = _new_user(db, created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), coin=100)
|
||||
db.commit()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
w._run_once_entry()
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
assert db.get(CoinAccount, uid).coin_balance == 100 # 没清
|
||||
log = db.execute(select(InactivityResetLog).where(InactivityResetLog.user_id == uid)).scalar_one()
|
||||
assert log.reason.endswith("dryrun") # 记了审计
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_worker_run_once_entry_executes(monkeypatch) -> None:
|
||||
@@ -338,6 +362,44 @@ def test_worker_run_once_entry_executes(monkeypatch) -> None:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_run_once_dry_run_records_audit_but_does_not_clear() -> None:
|
||||
"""dry-run:只写审计(标 dryrun)、不动钱、不预警;重复跑不重复记(streak dedup)。"""
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.integrations.notifier import LogNotifier
|
||||
from app.models.wallet import CoinAccount, CoinTransaction
|
||||
from app.repositories import inactivity
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
today = date(2026, 2, 1)
|
||||
old = _new_user(db, created_at=datetime(2026, 1, 10, tzinfo=timezone.utc), coin=100, cash=200, invite=300)
|
||||
warn_uid = _new_user(db, created_at=datetime(2026, 1, 22, tzinfo=timezone.utc), coin=50) # 预警窗
|
||||
db.commit()
|
||||
|
||||
stats = inactivity.run_once(db, notifier=LogNotifier(), reset_days=15,
|
||||
warn_stages=[7, 2], today=today, dry_run=True)
|
||||
acc = db.get(CoinAccount, old)
|
||||
assert (acc.coin_balance, acc.cash_balance_cents, acc.invite_cash_balance_cents) == (100, 200, 300) # 原封
|
||||
log = db.execute(select(InactivityResetLog).where(InactivityResetLog.user_id == old)).scalar_one()
|
||||
assert log.coin_balance_before == 100 and log.reason.endswith("dryrun") # 审计标 dryrun
|
||||
assert db.execute(select(CoinTransaction).where(
|
||||
CoinTransaction.user_id == old, CoinTransaction.biz_type == "inactivity_reset")).first() is None # 无流水
|
||||
assert stats["warned"] == 0 # dry-run 不预警
|
||||
assert db.execute(select(InactivityNotificationLog).where(
|
||||
InactivityNotificationLog.user_id == warn_uid)).first() is None
|
||||
assert stats["cleared"] == 1 # dry-run:cleared=记了几条
|
||||
|
||||
# 再跑一次 → 不重复记(dedup),余额仍原封
|
||||
inactivity.run_once(db, notifier=LogNotifier(), reset_days=15, warn_stages=[7, 2], today=today, dry_run=True)
|
||||
assert len(db.execute(select(InactivityResetLog).where(
|
||||
InactivityResetLog.user_id == old)).scalars().all()) == 1
|
||||
assert db.get(CoinAccount, old).coin_balance == 100
|
||||
finally:
|
||||
db.rollback()
|
||||
db.close()
|
||||
|
||||
|
||||
def test_admin_list_users_last_active_ignores_login() -> None:
|
||||
"""admin 用户列表 last_active_at 改用共享口径:登录不算活跃(baseline=created_at)、只认活跃事件。"""
|
||||
from app.admin.repositories import queries
|
||||
|
||||
Reference in New Issue
Block a user