"""新手引导完成标记的读写(按 user_id + device_id 去重)。 登录时 [is_completed] 判断该 (账号, 设备) 是否走过引导;走完引导时 [mark_completed] 写一条。 device_id 为空(老客户端 / 取不到 ANDROID_ID)一律按"未完成"处理,即照常走引导,不误跳过。 """ from __future__ import annotations from sqlalchemy import select from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from app.models.onboarding import OnboardingCompletion def is_completed(db: Session, *, user_id: int, device_id: str) -> bool: """该 (账号, 设备) 是否已完成新手引导。device_id 为空 → 一律 False。""" if not device_id: return False stmt = select(OnboardingCompletion.id).where( OnboardingCompletion.user_id == user_id, OnboardingCompletion.device_id == device_id, ) return db.execute(stmt).first() is not None def mark_completed(db: Session, *, user_id: int, device_id: str) -> None: """走完引导时写入。device_id 为空忽略;同 (账号, 设备) 已存在则幂等(靠唯一约束兜并发)。""" if not device_id: return db.add(OnboardingCompletion(user_id=user_id, device_id=device_id)) try: db.commit() except IntegrityError: # 并发 / 重复提交撞唯一约束:已有行即视为成功。 db.rollback()