alabuga/backend/app/api/routes/users.py
2025-09-28 20:29:36 +03:00

93 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Маршруты работы с профилем."""
from __future__ import annotations
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session, selectinload
from app.api.deps import get_current_user
from app.db.session import get_db
from app.models.rank import Rank
from app.models.user import User, UserRole, UserCompetency
from app.models.mission import SubmissionStatus
from app.schemas.progress import ProgressSnapshot
from app.schemas.rank import RankBase
from app.schemas.user import LeaderboardEntry, UserCompetencyRead, UserProfile
from app.services.rank import build_progress_snapshot
router = APIRouter(prefix="/api", tags=["profile"])
@router.get("/me", response_model=UserProfile, summary="Профиль пилота")
def get_profile(
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
) -> UserProfile:
"""Возвращаем профиль и связанные сущности."""
db.refresh(current_user)
for item in current_user.competencies:
_ = item.competency
for artifact in current_user.artifacts:
_ = artifact.artifact
return UserProfile.model_validate(current_user)
@router.get("/ranks", response_model=list[RankBase], summary="Перечень рангов")
def list_ranks(
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
) -> list[RankBase]:
"""Возвращаем ранги по возрастанию требований."""
ranks = db.query(Rank).order_by(Rank.required_xp).all()
return [RankBase.model_validate(rank) for rank in ranks]
@router.get("/progress", response_model=ProgressSnapshot, summary="Прогресс до следующего ранга")
def get_progress(
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
) -> ProgressSnapshot:
"""Возвращаем агрегированную информацию о выполненных условиях следующего ранга."""
db.refresh(current_user)
_ = current_user.submissions
_ = current_user.competencies
snapshot = build_progress_snapshot(current_user, db)
return snapshot
@router.get("/leaderboard", response_model=list[LeaderboardEntry], summary="Лидерборд пилотов")
def leaderboard(
*, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
) -> list[LeaderboardEntry]:
"""Возвращаем пилотов, отсортированных по опыту с перечислением компетенций."""
users = (
db.query(User)
.filter(User.role == UserRole.PILOT)
.options(
selectinload(User.current_rank),
selectinload(User.competencies).selectinload(UserCompetency.competency),
selectinload(User.submissions),
)
.order_by(User.xp.desc(), User.created_at)
.all()
)
leaderboard: list[LeaderboardEntry] = []
for user in users:
completed = sum(1 for submission in user.submissions if submission.status == SubmissionStatus.APPROVED)
competencies = [UserCompetencyRead.model_validate(entry) for entry in user.competencies]
leaderboard.append(
LeaderboardEntry(
user_id=user.id,
full_name=user.full_name,
rank_title=user.current_rank.title if user.current_rank else None,
xp=user.xp,
mana=user.mana,
completed_missions=completed,
competencies=competencies,
)
)
return leaderboard