v0.1 - макет интерфейса, аутентификация через логин, аккаунт админа, создание партии в 2 этапа, базовые настройки профиля и группы, переключение между группами, статистика

This commit is contained in:
2026-06-16 17:41:06 +03:00
parent 6ab74f01aa
commit 56b5d09a4d
123 changed files with 13572 additions and 21 deletions
@@ -0,0 +1,92 @@
"""Членство в группе: список, добавление по нику, удаление, смена роли."""
from __future__ import annotations
from sqlmodel import Session, select
from app.core.errors import ConflictError, ForbiddenError, NotFoundError, ValidationError
from app.models import Group, GroupMember, User
MAX_GROUP_SIZE = 10
def list_members(session: Session, group_id: int) -> list[tuple[GroupMember, User]]:
rows = session.exec(
select(GroupMember, User)
.join(User, User.id == GroupMember.user_id)
.where(GroupMember.group_id == group_id)
.order_by(GroupMember.role.desc(), User.nickname)
).all()
return [(m, u) for m, u in rows]
def add_member_by_nickname(session: Session, group: Group, nickname: str) -> tuple[GroupMember, User]:
nickname = (nickname or "").strip()
if not nickname:
raise ValidationError("Укажите никнейм игрока.")
user = session.exec(select(User).where(User.nickname == nickname)).first()
if user is None:
raise NotFoundError("Игрок с таким ником не найден.")
member_count = len(
session.exec(select(GroupMember.id).where(GroupMember.group_id == group.id)).all()
)
if member_count >= MAX_GROUP_SIZE:
raise ConflictError(f"В группе уже максимум участников ({MAX_GROUP_SIZE}).")
existing = session.exec(
select(GroupMember).where(
GroupMember.group_id == group.id, GroupMember.user_id == user.id
)
).first()
if existing is not None:
raise ConflictError("Игрок уже в группе.")
member = GroupMember(group_id=group.id, user_id=user.id, role="member") # type: ignore[arg-type]
session.add(member)
session.commit()
session.refresh(member)
return member, user
def remove_member(session: Session, group: Group, user_id: int) -> None:
member = session.exec(
select(GroupMember).where(
GroupMember.group_id == group.id, GroupMember.user_id == user_id
)
).first()
if member is None:
raise NotFoundError("Игрок не состоит в группе.")
if member.role == "owner":
owners = session.exec(
select(GroupMember).where(
GroupMember.group_id == group.id, GroupMember.role == "owner"
)
).all()
if len(owners) <= 1:
raise ForbiddenError("Нельзя удалить последнего владельца группы.")
# Сбросить активную группу у тех, для кого она была активной.
user = session.get(User, user_id)
if user is not None and user.active_group_id == group.id:
user.active_group_id = None
session.add(user)
session.delete(member)
session.commit()
def change_role(session: Session, group: Group, user_id: int, role: str) -> GroupMember:
if role not in ("owner", "member"):
raise ValidationError("Недопустимая роль.")
member = session.exec(
select(GroupMember).where(
GroupMember.group_id == group.id, GroupMember.user_id == user_id
)
).first()
if member is None:
raise NotFoundError("Игрок не состоит в группе.")
member.role = role
session.add(member)
session.commit()
session.refresh(member)
return member