diff --git a/handlers/admin/settings/keyboard.py b/handlers/admin/settings/keyboard.py index 02938277..8c0c0bd6 100644 --- a/handlers/admin/settings/keyboard.py +++ b/handlers/admin/settings/keyboard.py @@ -97,15 +97,64 @@ def build_settings_buttons_kb(buttons_state: dict[str, bool]) -> InlineKeyboardM def build_settings_cashboxes_kb(providers_state: dict[str, bool]) -> InlineKeyboardMarkup: + order_button = InlineKeyboardButton( + text="📋 Порядок касс", + callback_data=AdminPanelCallback(action="settings_providers_order").pack(), + ) return build_toggle_section_keyboard( titles=PAYMENT_PROVIDER_TITLES, state=providers_state, action="settings_cashbox_toggle", columns=2, back_action="settings", + extra_rows=[[order_button]], ) +def build_providers_order_kb(sorted_names: list[str]) -> InlineKeyboardMarkup: + """Клавиатура для управления порядком отображения касс.""" + builder = InlineKeyboardBuilder() + + for idx, name in enumerate(sorted_names): + title = PAYMENT_PROVIDER_TITLES.get(name, name) + pos = idx + 1 + builder.row( + InlineKeyboardButton( + text="⬆️", + callback_data=AdminPanelCallback( + action="settings_order_up", page=pos, + ).pack(), + ), + InlineKeyboardButton( + text=f"{pos}. {title}", + callback_data=AdminPanelCallback( + action="settings_providers_order", + ).pack(), + ), + InlineKeyboardButton( + text="⬇️", + callback_data=AdminPanelCallback( + action="settings_order_down", page=pos, + ).pack(), + ), + ) + + builder.row( + InlineKeyboardButton( + text="🔄 Сбросить порядок", + callback_data=AdminPanelCallback(action="settings_order_reset").pack(), + ) + ) + builder.row( + InlineKeyboardButton( + text="Назад", + callback_data=AdminPanelCallback(action="settings_cashboxes").pack(), + ) + ) + + return builder.as_markup() + + def build_settings_notifications_kb(notifications_state: dict[str, object]) -> InlineKeyboardMarkup: intervals_button = InlineKeyboardButton( text="Интервалы", diff --git a/handlers/admin/settings/settings_cashboxes.py b/handlers/admin/settings/settings_cashboxes.py index 548683b3..4e476a82 100644 --- a/handlers/admin/settings/settings_cashboxes.py +++ b/handlers/admin/settings/settings_cashboxes.py @@ -3,10 +3,12 @@ from aiogram.types import CallbackQuery from sqlalchemy.ext.asyncio import AsyncSession from core.bootstrap import PAYMENTS_CONFIG, update_payments_config +from core.settings.providers_order_config import PROVIDERS_ORDER, update_providers_order from filters.admin import IsAdminFilter +from handlers.payments.providers import PROVIDERS_BASE, _get_effective_order from ..panel.keyboard import AdminPanelCallback -from .keyboard import PAYMENT_PROVIDER_TITLES, build_settings_cashboxes_kb +from .keyboard import PAYMENT_PROVIDER_TITLES, build_providers_order_kb, build_settings_cashboxes_kb router = Router(name="admin_settings_cashboxes") @@ -18,6 +20,15 @@ async def load_payment_providers_settings() -> dict[str, bool]: return {k: bool(config.get(k, False)) for k in PAYMENT_PROVIDER_TITLES.keys()} +def _get_sorted_provider_names() -> list[str]: + """Возвращает все провайдеры, отсортированные по текущему порядку.""" + all_names = list(PROVIDERS_BASE.keys()) + return sorted( + all_names, + key=lambda n: _get_effective_order(n, PROVIDERS_BASE.get(n, {})), + ) + + @router.callback_query(AdminPanelCallback.filter(F.action == "settings_cashboxes")) async def open_settings_cashboxes_menu(callback: CallbackQuery, session: AsyncSession) -> None: providers_state = await load_payment_providers_settings() @@ -56,3 +67,85 @@ async def toggle_cashbox_setting( reply_markup=build_settings_cashboxes_kb(updated_state), ) await callback.answer("Настройка обновлена") + +@router.callback_query(AdminPanelCallback.filter(F.action == "settings_providers_order")) +async def open_providers_order_menu(callback: CallbackQuery, session: AsyncSession) -> None: + sorted_names = _get_sorted_provider_names() + text = ( + "📋 Порядок отображения касс\n\n" + "⬆️ — поднять выше\n" + "⬇️ — опустить ниже\n\n" + "Порядок влияет на меню оплаты и fast flow." + ) + await callback.message.edit_text( + text=text, + reply_markup=build_providers_order_kb(sorted_names), + ) + await callback.answer() + + +@router.callback_query(AdminPanelCallback.filter(F.action == "settings_order_up")) +async def move_provider_up( + callback: CallbackQuery, + callback_data: AdminPanelCallback, + session: AsyncSession, +) -> None: + sorted_names = _get_sorted_provider_names() + idx = callback_data.page - 1 + + if idx <= 0: + await callback.answer("Уже на первом месте", show_alert=False) + return + + if idx >= len(sorted_names): + await callback.answer("Неизвестная касса", show_alert=True) + return + + sorted_names[idx], sorted_names[idx - 1] = sorted_names[idx - 1], sorted_names[idx] + + new_order = {name: (i + 1) * 10 for i, name in enumerate(sorted_names)} + await update_providers_order(session, new_order) + + await callback.message.edit_reply_markup( + reply_markup=build_providers_order_kb(sorted_names), + ) + await callback.answer("✅ Перемещено выше") + + +@router.callback_query(AdminPanelCallback.filter(F.action == "settings_order_down")) +async def move_provider_down( + callback: CallbackQuery, + callback_data: AdminPanelCallback, + session: AsyncSession, +) -> None: + sorted_names = _get_sorted_provider_names() + idx = callback_data.page - 1 + + if idx >= len(sorted_names) - 1: + await callback.answer("Уже на последнем месте", show_alert=False) + return + + if idx < 0: + await callback.answer("Неизвестная касса", show_alert=True) + return + + sorted_names[idx], sorted_names[idx + 1] = sorted_names[idx + 1], sorted_names[idx] + + new_order = {name: (i + 1) * 10 for i, name in enumerate(sorted_names)} + await update_providers_order(session, new_order) + + await callback.message.edit_reply_markup( + reply_markup=build_providers_order_kb(sorted_names), + ) + await callback.answer("✅ Перемещено ниже") + + +@router.callback_query(AdminPanelCallback.filter(F.action == "settings_order_reset")) +async def reset_providers_order(callback: CallbackQuery, session: AsyncSession) -> None: + await update_providers_order(session, {}) + + sorted_names = _get_sorted_provider_names() + await callback.message.edit_reply_markup( + reply_markup=build_providers_order_kb(sorted_names), + ) + await callback.answer("✅ Порядок сброшен на дефолтный")