diff --git a/src/quizzi/application/bot/handlers.py b/src/quizzi/application/bot/handlers.py index 59344ed..4dbff34 100644 --- a/src/quizzi/application/bot/handlers.py +++ b/src/quizzi/application/bot/handlers.py @@ -32,8 +32,9 @@ async def ensure_user_registered( existing_user = await user_dao.get_by_id(message.from_user.id) groups = await group_dao.get_all() + has_groups = len(groups) > 0 - start_data = {"user_id": message.from_user.id} + start_data = {"user_id": message.from_user.id, "has_groups": has_groups} if pending_test_id: start_data["pending_test_id"] = pending_test_id @@ -44,28 +45,30 @@ async def ensure_user_registered( username=message.from_user.username, last_name=message.from_user.last_name, ) - if len(groups) > 0: - await dialog_manager.start( - UserRegistrationSG.input_name, - mode=StartMode.RESET_STACK, - data=start_data - ) - return False - return True + await dialog_manager.start( + UserRegistrationSG.input_name, + mode=StartMode.RESET_STACK, + data=start_data + ) + return False - if len(groups) > 0 and (existing_user.name is None or existing_user.group is None): - if existing_user.name is None: - await dialog_manager.start( - UserRegistrationSG.input_name, - mode=StartMode.RESET_STACK, - data=start_data - ) - else: - await dialog_manager.start( - UserRegistrationSG.select_group, - mode=StartMode.RESET_STACK, - data=start_data - ) + needs_name = existing_user.name is None + needs_group = has_groups and existing_user.group is None + + if needs_name: + await dialog_manager.start( + UserRegistrationSG.input_name, + mode=StartMode.RESET_STACK, + data=start_data + ) + return False + + if needs_group: + await dialog_manager.start( + UserRegistrationSG.select_group, + mode=StartMode.RESET_STACK, + data=start_data + ) return False await user_dao.upsert( diff --git a/src/quizzi/application/bot/shared_dialogs/templates.py b/src/quizzi/application/bot/shared_dialogs/templates.py index 0f4699e..83f8754 100644 --- a/src/quizzi/application/bot/shared_dialogs/templates.py +++ b/src/quizzi/application/bot/shared_dialogs/templates.py @@ -22,13 +22,18 @@ from quizzi.infrastructure.database.repo.test import TestRepository TEMPLATES_INFO = ( "📦 Шаблоны тестов\n\n" - "Шаблоны позволяют экспортировать и импортировать тесты в формате JSON.\n\n" - "🔹 Экспорт — сохраните тест как файл для резервной копии или передачи\n" - "🔹 Импорт — загрузите тест из файла\n" - "🔹 Спецификация — описание формата JSON для создания тестов вручную" + "Экспорт и импорт тестов в формате JSON\n\n" + "
" + "📤 Экспорт\n" + "Сохранение теста в файл для резервной копии или передачи\n\n" + "📥 Импорт\n" + "Загрузка теста из JSON файла\n\n" + "📋 Спецификация\n" + "Описание формата теста для ручного создания" + "" ) -SPEC_INFO = """📋 Спецификация формата JSON +SPEC_INFO = """📋 Спецификация формата теста в JSON Структура файла:
{
diff --git a/src/quizzi/application/bot/user_dialogs/deeplink.py b/src/quizzi/application/bot/user_dialogs/deeplink.py
index 93f9ae4..66dd043 100644
--- a/src/quizzi/application/bot/user_dialogs/deeplink.py
+++ b/src/quizzi/application/bot/user_dialogs/deeplink.py
@@ -12,7 +12,7 @@ from quizzi.infrastructure.database.models import QuestionType
from quizzi.infrastructure.database.repo.test import TestRepository
from quizzi.infrastructure.database.repo.test_attempt import TestAttemptRepository
from quizzi.infrastructure.utils.rate_limiter import PasswordRateLimiter
-from quizzi.infrastructure.utils.timezone import now_msk_naive
+from quizzi.infrastructure.utils.timezone import now_msk_naive, to_msk
@inject
@@ -20,12 +20,15 @@ async def get_deeplink_test_data(
dialog_manager: DialogManager,
test_dao: FromDishka[TestDAO],
test_repo: FromDishka[TestRepository],
+ attempt_repo: FromDishka[TestAttemptRepository],
**_kwargs,
):
+ assert dialog_manager.event.from_user is not None
start_data = dialog_manager.start_data or {}
assert isinstance(start_data, dict)
test_id = start_data.get("test_id")
error = start_data.get("error")
+ user_id = dialog_manager.event.from_user.id
if error:
return {"test_info": error, "can_start": False}
@@ -40,17 +43,26 @@ async def get_deeplink_test_data(
questions_count = await test_repo.count_questions_in_test(test_id)
+ attempts = await attempt_repo.get_user_test_attempts(user_id, test_id)
+ finished_attempts = [a for a in attempts if a.finished_at]
+
password_str = "🔒 Требуется пароль" if test.password else "🔓 Без пароля"
- attempts_str = f"🔄 Попыток: {test.attempts}" if test.attempts else "🔄 Попыток: ♾️"
+ attempts_str = f"🔄 Попыток: {len(finished_attempts)}/{test.attempts}" if test.attempts else f"🔄 Попыток: {len(finished_attempts)}/♾️"
time_limit_str = f"⏱️ Время: {test.time_limit // 60} мин" if test.time_limit else "⏱️ Без лимита"
+ expires_at_msk = to_msk(test.expires_at)
+ expires_str = f"📅 До {expires_at_msk.strftime('%d.%m.%Y %H:%M')}" if expires_at_msk else "📅 Без срока"
+ group_str = f"🎓 Для группы {test.for_group}" if test.for_group else "👥 Для всех"
+
test_info = (
f"📝 {test.title}\n\n"
f"{test.description or '—'}
\n\n"
f"Вопросов: {questions_count}\n"
f"{password_str}\n"
f"{attempts_str}\n"
- f"{time_limit_str}"
+ f"{time_limit_str}\n"
+ f"{expires_str}\n"
+ f"{group_str}"
)
return {"test_info": test_info, "can_start": True, "has_password": bool(test.password)}
diff --git a/src/quizzi/application/bot/user_dialogs/main_menu.py b/src/quizzi/application/bot/user_dialogs/main_menu.py
index 5bc8895..6b04c1c 100644
--- a/src/quizzi/application/bot/user_dialogs/main_menu.py
+++ b/src/quizzi/application/bot/user_dialogs/main_menu.py
@@ -436,7 +436,7 @@ user_menu_dialog = Dialog(
getter=get_test_detail,
),
Window(
- Const("✏️ Изменение имени\n\nВведите новое имя:"),
+ Const("✏️ Изменение имени\n\nВведите имя и фамилию:"),
MessageInput(on_name_input),
Button(Const("◀️ Назад"), id="back", on_click=on_back_to_main),
state=UserMenuSG.edit_name,
diff --git a/src/quizzi/application/bot/user_dialogs/registration.py b/src/quizzi/application/bot/user_dialogs/registration.py
index 6e12ed1..8b5407a 100644
--- a/src/quizzi/application/bot/user_dialogs/registration.py
+++ b/src/quizzi/application/bot/user_dialogs/registration.py
@@ -9,6 +9,7 @@ from dishka.integrations.aiogram_dialog import inject
from quizzi.application.bot.user_dialogs.states import UserDeeplinkSG, UserMenuSG, UserRegistrationSG
from quizzi.infrastructure.database.dao.group import GroupDAO
from quizzi.infrastructure.database.dao.user import UserDAO
+from quizzi.infrastructure.utils.timezone import now_msk_naive
@inject
@@ -35,11 +36,24 @@ async def on_name_input(
start_data = manager.start_data or {}
assert isinstance(start_data, dict)
user_id = start_data.get("user_id")
+ has_groups = start_data.get("has_groups", True)
+ pending_test_id = start_data.get("pending_test_id")
+
if user_id:
- await user_dao.update(user_id=user_id, name=name)
+ await user_dao.update(user_id=user_id, name=name, name_updated_at=now_msk_naive())
manager.dialog_data["name"] = name
- await manager.switch_to(UserRegistrationSG.select_group)
+
+ if has_groups:
+ await manager.switch_to(UserRegistrationSG.select_group)
+ elif pending_test_id:
+ await manager.start(
+ UserDeeplinkSG.test_preview,
+ mode=StartMode.RESET_STACK,
+ data={"test_id": pending_test_id}
+ )
+ else:
+ await manager.start(UserMenuSG.main, mode=StartMode.RESET_STACK)
@inject
@@ -66,7 +80,7 @@ async def on_group_selected(
pending_test_id = start_data.get("pending_test_id")
if user_id:
- await user_dao.update(user_id=user_id, group=int(item_id))
+ await user_dao.update(user_id=user_id, group=int(item_id), group_updated_at=now_msk_naive())
if pending_test_id:
await manager.start(