feat: кнопка 'Просмотреть все счета' при массовом добавлении (>50)
Some checks reported errors
continuous-integration/drone/push Build encountered an error

This commit is contained in:
2025-11-18 16:26:46 +09:00
parent 10e257c798
commit 9d59248769

View File

@@ -22,6 +22,14 @@ class AddAccountStates(StatesGroup):
choosing_lottery = State() choosing_lottery = State()
@router.message(Command("cancel"))
@admin_only
async def cancel_command(message: Message, state: FSMContext):
"""Отменить текущую операцию и сбросить состояние"""
await state.clear()
await message.answer("✅ Состояние сброшено. Все операции отменены.")
@router.message(Command("add_account")) @router.message(Command("add_account"))
@admin_only @admin_only
async def add_account_command(message: Message, state: FSMContext): async def add_account_command(message: Message, state: FSMContext):
@@ -120,9 +128,30 @@ async def process_accounts_data(message: Message, state: FSMContext):
return return
lines = message.text.strip().split('\n') lines = message.text.strip().split('\n')
# Ограничение: максимум 1000 счетов за раз
MAX_ACCOUNTS = 1000
if len(lines) > MAX_ACCOUNTS:
await message.answer(
f"⚠️ Слишком много счетов!\n\n"
f"Максимум за раз: {MAX_ACCOUNTS}\n"
f"Вы отправили: {len(lines)} строк\n\n"
f"Разделите данные на несколько частей."
)
await state.clear()
return
# Отправляем начальное уведомление
progress_msg = await message.answer(
f"⏳ Обработка {len(lines)} строк...\n"
f"Пожалуйста, подождите..."
)
accounts_data = [] accounts_data = []
errors = [] errors = []
BATCH_SIZE = 100 # Обрабатываем по 100 счетов за раз
# Универсальный парсер: поддержка однострочного и многострочного формата # Универсальный парсер: поддержка однострочного и многострочного формата
i = 0 i = 0
while i < len(lines): while i < len(lines):
@@ -177,6 +206,16 @@ async def process_accounts_data(message: Message, state: FSMContext):
'owner_id': owner.telegram_id if owner else None 'owner_id': owner.telegram_id if owner else None
}) })
# Обновляем progress каждые 50 счетов
if len(accounts_data) % 50 == 0:
try:
await progress_msg.edit_text(
f"⏳ Обработано: {len(accounts_data)} / ~{len(lines)}\n"
f"❌ Ошибок: {len(errors)}"
)
except:
pass # Игнорируем ошибки редактирования
except ValueError as e: except ValueError as e:
errors.append(f"Счет {account_number} (карта {club_card}): {str(e)}") errors.append(f"Счет {account_number} (карта {club_card}): {str(e)}")
except Exception as e: except Exception as e:
@@ -184,6 +223,12 @@ async def process_accounts_data(message: Message, state: FSMContext):
i += 1 i += 1
# Удаляем progress сообщение
try:
await progress_msg.delete()
except:
pass
# Группируем счета по владельцам и отправляем групповые уведомления # Группируем счета по владельцам и отправляем групповые уведомления
if accounts_data: if accounts_data:
from collections import defaultdict from collections import defaultdict
@@ -203,8 +248,13 @@ async def process_accounts_data(message: Message, state: FSMContext):
f"💳 `{account_numbers[0]}`\n\n" f"💳 `{account_numbers[0]}`\n\n"
"Теперь вы можете участвовать в розыгрышах!" "Теперь вы можете участвовать в розыгрышах!"
) )
else: await message.bot.send_message(
# Групповое уведомление owner_id,
notification_text,
parse_mode="Markdown"
)
elif len(account_numbers) <= 50:
# Групповое уведомление (до 50 счетов)
notification_text = ( notification_text = (
f"К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n" f"К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n"
"💳 *Ваши счета:*\n" "💳 *Ваши счета:*\n"
@@ -218,6 +268,31 @@ async def process_accounts_data(message: Message, state: FSMContext):
notification_text, notification_text,
parse_mode="Markdown" parse_mode="Markdown"
) )
else:
# Много счетов - показываем первые 10 и кнопку
notification_text = (
f"К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n"
"💳 *Первые 10 счетов:*\n"
)
for acc_num in account_numbers[:10]:
notification_text += f"• `{acc_num}`\n"
notification_text += f"\n_...и ещё {len(account_numbers) - 10} счетов_\n\n"
notification_text += "Теперь вы можете участвовать в розыгрышах!"
# Кнопка для просмотра всех счетов
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(
text="📋 Просмотреть все счета",
callback_data="view_my_accounts"
)]
])
await message.bot.send_message(
owner_id,
notification_text,
parse_mode="Markdown",
reply_markup=keyboard
)
except Exception as e: except Exception as e:
pass # Игнорируем ошибки отправки уведомлений pass # Игнорируем ошибки отправки уведомлений
@@ -627,3 +702,43 @@ async def user_info_command(message: Message):
except Exception as e: except Exception as e:
await message.answer(f"❌ Ошибка: {str(e)}") await message.answer(f"❌ Ошибка: {str(e)}")
@router.callback_query(F.data == "view_my_accounts")
async def view_my_accounts_callback(callback: CallbackQuery):
"""Показать все счета пользователя"""
try:
async with async_session_maker() as session:
# Получаем пользователя
user_result = await session.execute(
select(User).where(User.telegram_id == callback.from_user.id)
)
user = user_result.scalar_one_or_none()
if not user:
await callback.answer("❌ Пользователь не найден", show_alert=True)
return
# Получаем все счета
accounts = await AccountService.get_user_accounts(session, user.id)
if not accounts:
await callback.answer("У вас нет счетов", show_alert=True)
return
# Формируем сообщение с пагинацией (по 50 счетов на сообщение)
BATCH_SIZE = 50
for i in range(0, len(accounts), BATCH_SIZE):
batch = accounts[i:i+BATCH_SIZE]
text = f"💳 *Ваши счета ({i+1}-{min(i+BATCH_SIZE, len(accounts))} из {len(accounts)}):*\n\n"
for acc in batch:
status = "" if acc.is_active else ""
text += f"{status} `{acc.account_number}`\n"
await callback.message.answer(text, parse_mode="Markdown")
await callback.answer("✅ Список счетов отправлен")
except Exception as e:
await callback.answer(f"❌ Ошибка: {str(e)}", show_alert=True)