fix(user): 注销账号前置校验资金余额 + 释放微信/邀请码唯一约束

- delete_account 端点: 有可提现现金余额 / 在审提现单(reviewing)时拒绝注销(409), 防余额锁死在 deleted 行无法退出; pending 提现已在途不拦(对账 worker 不依赖 user.status)
- soft_delete_account: 注销连带清 wechat_openid/nickname/avatar(释放微信绑定槽, 否则该微信永久无法再被任何账号绑定→提现通道锁死) + invite_code(释放邀请码唯一槽)
- wallet 新增 get_cash_balance_cents(只读, 不建账户) 供注销前置校验; 复用 has_reviewing_withdraw
- 新增 tests/test_delete_account.py

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 02:03:33 +08:00
parent 95a07f75b7
commit d8358a6816
4 changed files with 177 additions and 2 deletions
+12
View File
@@ -18,6 +18,7 @@ from app.api.deps import CurrentUser, DbSession
from app.core import media
from app.repositories import onboarding as onboarding_repo
from app.repositories import user as user_repo
from app.repositories import wallet as wallet_repo
from app.schemas.auth import UserOut
from app.schemas.user import (
OkResponse,
@@ -87,6 +88,17 @@ def onboarding_status(
@router.delete("", response_model=OkResponse, summary="注销账号(软删除)")
def delete_account(user: CurrentUser, db: DbSession) -> OkResponse:
# 资金前置校验:注销是软删 + 匿名化,余额一旦留在 deleted 行就锁死(既退不出、新号也
# 拿不回)。有可提现现金 / 在审提现单 → 拒绝注销,引导用户先把钱处理掉。
# (pending 提现转账已在途、对账 worker 不依赖 user.status 照常到账,故不拦 pending。)
if wallet_repo.get_cash_balance_cents(db, user.id) > 0:
raise HTTPException(
status_code=409, detail="账户还有未提现的现金余额,请先提现后再注销"
)
if wallet_repo.has_reviewing_withdraw(db, user.id):
raise HTTPException(
status_code=409, detail="有提现正在审核中,请等审核完成后再注销"
)
media.delete_avatar(user.avatar_url)
user_repo.soft_delete_account(db, user)
logger.info("delete account user_id=%d", user.id)