Enhance login display with raffle participation history

- Show active vs closed raffles for each login
- Display win/loss status (🏆 for winners, ✗ for non-winners)
- Limit display to 5 active + 3 closed raffles
- Update help documentation with detailed status explanation
- Add status icons (/⏸️) for active/inactive logins
This commit is contained in:
2026-03-07 08:53:48 +09:00
parent 904f94e1b5
commit ede4617b00
2 changed files with 88 additions and 19 deletions

View File

@@ -150,24 +150,36 @@ async def help_logins(callback: CallbackQuery):
"В этом разделе вы всегда сможете найти свои добавленные логины в розыгрыши, " "В этом разделе вы всегда сможете найти свои добавленные логины в розыгрыши, "
"которые администратор указал для вас в системе.\n\n" "которые администратор указал для вас в системе.\n\n"
"⚠️ <b>Важное уточнение:</b>\n\n" "<b>Какая информация показывается?</b>\n\n"
"Имейте в виду, что логины, которые не отыграны по условиям розыгрыша, " "Для каждого логина вы сможете увидеть:\n"
"<b>не добавляются в список</b>. В списке отображаются только активные логины, " "🎲 <b>Активные розыгрыши</b> - розыгрыши в которых сейчас участвует логин\n"
"которые соответствуют условиям текущих и будущих розыгрышей.\n\n" "🏁 <b>Завершенные розыгрыши</b> - прошедшие розыгрыши:\n"
" 🏆 ВЫИГРАЛ - если логин победил (указано место)\n"
"Не выиграл - если логин не получил приз\n\n"
"⚠️ <b>Важное уточнение о статусе логинов:</b>\n\n"
"✅ <b>Зеленый (активный)</b> - логин участвует в новых розыгрышах\n"
"⏸️ <b>Серый (неактивный)</b> - логин не участвует в новых розыгрышах\n\n"
"Имейте в виду, что логины, которые участвовали в закрытых розыгрышах, "
"<b>не добавляются в новые розыгрыши</b>. В списке отображаются только те логины, "
"которые активны и соответствуют условиям текущих розыгрышей.\n\n"
"<b>Как это работает:</b>\n\n"
"1⃣ Если у вас есть 100 логинов\n"
"2⃣ 60 из них участвовали в прошедших/закрытых розыгрышах\n"
"3⃣ Статус этих 60 логинов будет ⏸️ (неактивны)\n"
"4⃣ Они не добавляются в новые розыгрыши\n"
"5В новых розыгрышах участвуют только оставшиеся активные логины\n\n"
"<b>Как использовать:</b>\n\n" "<b>Как использовать:</b>\n\n"
"1⃣ Откройте главное меню\n" "1⃣ Откройте главное меню\n"
"2⃣ Нажмите кнопку <i>\"Мои логины\"</i>\n" "2⃣ Нажмите кнопку <i>\"Мои логины\"</i>\n"
"3⃣ Вы увидите список всех ваших активных логинов\n\n" "3⃣ Вы увидите полный список всех ваших логинов с информацией\n\n"
"📋 <b>Что показывается:</b>\n\n"
" ✅ Активные логины, добавленные администратором\n"
" ✅ Логины, соответствующие условиям розыгрышей\n"
" ❌ Неотыгранные логины (в них не проводятся розыгрыши)\n\n"
"💡 <b>Совет:</b>\n" "💡 <b>Совет:</b>\n"
"Если вы не видите ожидаемый логин в списке, это значит, что он не соответствует " "Если вы не видите ожидаемый логин в списке активных розыгрышей, "
"условиям текущих розыгрышей или администратор еще не добавил его в систему. " "это может означать, что он уже участвовал в закрытых розыгрышах и помечен как неактивный. "
"Свяжитесь с администратором для уточнения.\n\n" "Свяжитесь с администратором для уточнения.\n\n"
"🔄 <b>Обновление информации:</b>\n" "🔄 <b>Обновление информации:</b>\n"

View File

@@ -2,6 +2,8 @@
from aiogram import Router, F from aiogram import Router, F
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.filters import Command, StateFilter from aiogram.filters import Command, StateFilter
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from src.filters.case_insensitive import CaseInsensitiveCommand from src.filters.case_insensitive import CaseInsensitiveCommand
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
@@ -11,6 +13,7 @@ import logging
from src.core.database import async_session_maker from src.core.database import async_session_maker
from src.core.registration_services import RegistrationService, AccountService from src.core.registration_services import RegistrationService, AccountService
from src.core.services import UserService from src.core.services import UserService
from src.core.models import Participation, Winner, Lottery
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
router = Router() router = Router()
@@ -222,7 +225,7 @@ async def show_verification_code(message: Message):
@router.message(Command("my_accounts")) @router.message(Command("my_accounts"))
async def show_user_accounts(message: Message): async def show_user_accounts(message: Message):
"""Показать счета пользователя""" """Показать логины пользователя с информацией о розыгрышах"""
async with async_session_maker() as session: async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, message.from_user.id) user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
@@ -234,15 +237,69 @@ async def show_user_accounts(message: Message):
if not accounts: if not accounts:
await message.answer( await message.answer(
"У вас пока нет привязанных счетов.\n\n" "У вас пока нет привязанных логинов.\n\n"
"Счета добавляются администратором." "Логины добавляются администратором."
) )
return return
text = f"💳 Ваши счета (Клубная карта: {user.club_card_number}):\n\n" text = f"📱 <b>Ваши логины</b> (Клубная карта: {user.club_card_number})\n\n"
for i, account in enumerate(accounts, 1): for i, account in enumerate(accounts, 1):
status = "" if account.is_active else "" # Получаем participations для этого account с загруженными данными о lottery
text += f"{i}. {status} {account.account_number}\n" participations = await session.execute(
select(Participation)
.where(Participation.account_id == account.id)
.options(selectinload(Participation.lottery))
)
participations = participations.scalars().all()
# Определяем статус логина
active_participations = [p for p in participations if not p.lottery.is_completed]
closed_participations = [p for p in participations if p.lottery.is_completed]
# Основная информация о логине
status_icon = "" if account.is_active and active_participations else "⏸️"
text += f"{i}. {status_icon} <b>{account.account_number}</b>\n"
if active_participations:
text += " 🎲 <b>Активные розыгрыши:</b>\n"
for p in active_participations[:5]: # Показываем не более 5
status = "🟢"
text += f" {status} {p.lottery.title}\n"
if len(active_participations) > 5:
text += f" ... и еще {len(active_participations) - 5}\n"
if closed_participations:
text += " 🏁 <b>Завершенные розыгрыши:</b>\n"
for p in closed_participations[:3]: # Показываем не более 3
# Проверяем, выиграл ли в этом розыгрыше
winner_result = await session.execute(
select(Winner)
.where(
(Winner.lottery_id == p.lottery_id) &
(Winner.account_number == account.account_number)
)
)
winner = winner_result.scalar_one_or_none()
if winner:
text += f" 🏆 {p.lottery.title} - <b>ВЫИГРАЛ!</b> ({winner.place} место)\n"
else:
text += f"{p.lottery.title}\n"
if len(closed_participations) > 3:
text += f" ... и еще {len(closed_participations) - 3} закрытых\n"
if not participations:
text += " В розыгрышах не участвовал\n"
text += "\n"
await message.answer(text) # Добавляем примечание о неактивных логинах
if any(not acc.is_active for acc in accounts):
text += "⏸️ - Логин не участвует в новых розыгрышах\n"
text += "✅ - Логин активен и может участвовать\n\n"
text += "💡 <b>Заметка:</b> Логины, участвовавшие в закрытых розыгрышах, не добавляются в новые розыгрыши."
await message.answer(text, parse_mode="HTML")