diff --git a/handlers/admin/users/keyboard.py b/handlers/admin/users/keyboard.py index b1456c13..a9051d8d 100644 --- a/handlers/admin/users/keyboard.py +++ b/handlers/admin/users/keyboard.py @@ -115,9 +115,29 @@ def build_users_balance_change_kb(tg_id: int) -> InlineKeyboardMarkup: return builder.as_markup() -async def build_users_balance_kb(session: AsyncSession, tg_id: int) -> InlineKeyboardMarkup: +async def build_users_balance_kb( + session: AsyncSession, tg_id: int, page: int = 0, total_pages: int = 1, +) -> InlineKeyboardMarkup: builder = InlineKeyboardBuilder() + if total_pages > 1: + nav_buttons = [] + if page > 0: + nav_buttons.append(InlineKeyboardButton( + text="◀️", + callback_data=AdminUserEditorCallback(action="users_balance_page", tg_id=tg_id, data=page - 1).pack(), + )) + nav_buttons.append(InlineKeyboardButton( + text=f"{page + 1}/{total_pages}", + callback_data="noop", + )) + if page < total_pages - 1: + nav_buttons.append(InlineKeyboardButton( + text="▶️", + callback_data=AdminUserEditorCallback(action="users_balance_page", tg_id=tg_id, data=page + 1).pack(), + )) + builder.row(*nav_buttons) + for amount in [100, 250, 500, 1000]: builder.row( InlineKeyboardButton( diff --git a/handlers/admin/users/users_balance.py b/handlers/admin/users/users_balance.py index edf3fbdb..efd0e6bc 100644 --- a/handlers/admin/users/users_balance.py +++ b/handlers/admin/users/users_balance.py @@ -3,7 +3,7 @@ from datetime import datetime from aiogram import F, Router from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery, Message -from sqlalchemy import select +from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from database import get_balance, set_user_balance, update_balance @@ -30,15 +30,67 @@ def format_admin_operation(amount: float, created_at: datetime) -> str: return f"\n
Админ {sign}{abs_amount}Р\n⏳ Дата: {date_str}
" -def format_user_payment(amount: float, created_at: datetime, payment_system: str, status: str) -> str: +def format_user_payment( + amount: float, created_at: datetime, payment_system: str, status: str, payment_id: str | None = None, +) -> str: date_str = created_at.strftime("%Y-%m-%d %H:%M:%S") abs_amount = abs(amount) system_name = payment_system or "Неизвестно" + pid = f"{payment_id}" if payment_id else "—" return ( - f"\n
💸 Сумма: {abs_amount} | {system_name}\n📌 Статус: {status}\n⏳ Дата: {date_str}
" + f"\n
💸 Сумма: {abs_amount} | {system_name}\n" + f"📌 Статус: {status}\n" + f"🆔 ID: {pid}\n" + f"⏳ Дата: {date_str}
" ) +async def _render_balance_page( + callback_query: CallbackQuery, + session: AsyncSession, + tg_id: int, + page: int = 0, +): + balance = await get_balance(session, tg_id) + balance = int(balance or 0) + + total_count_result = await session.execute( + select(func.count()).where(Payment.tg_id == tg_id) + ) + total = total_count_result.scalar() or 0 + + total_pages = max(1, (total + 4) // 5) + page = max(0, min(page, total_pages - 1)) + + stmt = ( + select( + Payment.amount, + Payment.created_at, + Payment.payment_system, + Payment.status, + Payment.payment_id, + ) + .where(Payment.tg_id == tg_id) + .order_by(Payment.created_at.desc()) + .offset(page * 5) + .limit(5) + ) + result = await session.execute(stmt) + records = result.all() + + text = f"💵 Изменение баланса\n\n🆔 ID: {tg_id}\n💰 Баланс: {balance}Р" + text += f"\n\n📊 Все операции ({total}), стр. {page + 1}/{total_pages}:" + + if records: + for amount, created_at, payment_system, status, payment_id in records: + text += format_user_payment(amount, created_at, payment_system, status, payment_id) + else: + text += "\n🚫 Операции отсутствуют" + + kb = await build_users_balance_kb(session, tg_id, page=page, total_pages=total_pages) + await callback_query.message.edit_text(text=text, reply_markup=kb) + + @router.callback_query( AdminUserEditorCallback.filter(F.action == "users_balance_edit"), IsAdminFilter(), @@ -48,49 +100,21 @@ async def handle_balance_change( callback_data: AdminUserEditorCallback, session: AsyncSession, ): - tg_id = callback_data.tg_id + page = int(callback_data.data) if callback_data.data is not None else 0 + await _render_balance_page(callback_query, session, callback_data.tg_id, page) - balance = await get_balance(session, tg_id) - balance = int(balance or 0) - stmt_admin = ( - select(Payment.amount, Payment.created_at) - .where(Payment.tg_id == tg_id, Payment.payment_system == "admin") - .order_by(Payment.created_at.desc()) - .limit(5) - ) - result_admin = await session.execute(stmt_admin) - admin_records = result_admin.all() - - stmt_user = ( - select(Payment.amount, Payment.created_at, Payment.payment_system, Payment.status) - .where(Payment.tg_id == tg_id, Payment.payment_system != "admin") - .order_by(Payment.created_at.desc()) - .limit(5) - ) - result_user = await session.execute(stmt_user) - user_records = result_user.all() - - text = f"💵 Изменение баланса\n\n🆔 ID: {tg_id}\n💰 Баланс: {balance}Р" - - text += "\n\n📊 Операции админа (5):" - if admin_records: - for amount, created_at in admin_records: - text += format_admin_operation(amount, created_at) - else: - text += "\n🚫 Операции отсутствуют" - - text += "\n\n📊 Последние операции (5):" - if user_records: - for amount, created_at, payment_system, status in user_records: - text += format_user_payment(amount, created_at, payment_system, status) - else: - text += "\n🚫 Операции отсутствуют" - - await callback_query.message.edit_text( - text=text, - reply_markup=await build_users_balance_kb(session, tg_id), - ) +@router.callback_query( + AdminUserEditorCallback.filter(F.action == "users_balance_page"), + IsAdminFilter(), +) +async def handle_balance_page( + callback_query: CallbackQuery, + callback_data: AdminUserEditorCallback, + session: AsyncSession, +): + page = int(callback_data.data) if callback_data.data is not None else 0 + await _render_balance_page(callback_query, session, callback_data.tg_id, page) @router.callback_query(