From 8e126097463d1d45dc57ff663e0f5eae131739f5 Mon Sep 17 00:00:00 2001 From: Egor Date: Sat, 4 Oct 2025 02:39:16 +0300 Subject: [PATCH] Add admin tariffs menu scaffolding --- app/bot.py | 4 +- app/handlers/admin/main.py | 26 +++++- app/handlers/admin/tariffs.py | 101 ++++++++++++++++++++++++ app/keyboards/admin.py | 35 ++++++++ app/localization/default_locales/en.yml | 13 +++ app/localization/default_locales/ru.yml | 13 +++ app/localization/locales/en.json | 12 +++ app/localization/locales/ru.json | 12 +++ 8 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 app/handlers/admin/tariffs.py diff --git a/app/bot.py b/app/bot.py index 36532569..649208c3 100644 --- a/app/bot.py +++ b/app/bot.py @@ -33,6 +33,7 @@ from app.handlers.admin import ( maintenance as admin_maintenance, promo_groups as admin_promo_groups, campaigns as admin_campaigns, + tariffs as admin_tariffs, user_messages as admin_user_messages, updates as admin_updates, backup as admin_backup, @@ -126,7 +127,8 @@ async def setup_bot() -> tuple[Bot, Dispatcher]: admin_main.register_handlers(dp) admin_users.register_handlers(dp) admin_subscriptions.register_handlers(dp) - admin_servers.register_handlers(dp) + admin_servers.register_handlers(dp) + admin_tariffs.register_handlers(dp) admin_promocodes.register_handlers(dp) admin_messages.register_handlers(dp) admin_monitoring.register_handlers(dp) diff --git a/app/handlers/admin/main.py b/app/handlers/admin/main.py index c6f2bbe1..3e08c109 100644 --- a/app/handlers/admin/main.py +++ b/app/handlers/admin/main.py @@ -11,6 +11,7 @@ from app.keyboards.admin import ( get_admin_promo_submenu_keyboard, get_admin_communications_submenu_keyboard, get_admin_support_submenu_keyboard, + get_admin_tariffs_submenu_keyboard, get_admin_settings_submenu_keyboard, get_admin_system_submenu_keyboard ) @@ -147,6 +148,24 @@ async def show_support_submenu( await callback.answer() +@admin_required +@error_handler +async def show_tariffs_submenu( + callback: types.CallbackQuery, + db_user: User, + db: AsyncSession +): + texts = get_texts(db_user.language) + + await callback.message.edit_text( + texts.t("ADMIN_TARIFFS_SUBMENU_TITLE", "🧾 **Тарифы**\n\n") + + texts.t("ADMIN_TARIFFS_SUBMENU_DESCRIPTION", "Управление тарифным режимом и подготовка функций:"), + reply_markup=get_admin_tariffs_submenu_keyboard(db_user.language), + parse_mode="Markdown" + ) + await callback.answer() + + # Moderator panel entry (from main menu quick button) async def show_moderator_panel( callback: types.CallbackQuery, @@ -402,7 +421,12 @@ def register_handlers(dp: Dispatcher): show_promo_submenu, F.data == "admin_submenu_promo" ) - + + dp.callback_query.register( + show_tariffs_submenu, + F.data == "admin_submenu_tariffs" + ) + dp.callback_query.register( show_communications_submenu, F.data == "admin_submenu_communications" diff --git a/app/handlers/admin/tariffs.py b/app/handlers/admin/tariffs.py new file mode 100644 index 00000000..ca631e9d --- /dev/null +++ b/app/handlers/admin/tariffs.py @@ -0,0 +1,101 @@ +from aiogram import Dispatcher, F, types +from sqlalchemy.ext.asyncio import AsyncSession + +from app.database.models import User +from app.keyboards.admin import get_admin_tariffs_submenu_keyboard +from app.localization.texts import get_texts +from app.utils.decorators import admin_required, error_handler + + +async def _show_placeholder( + callback: types.CallbackQuery, + db_user: User, + text_key: str, + default_text: str, + *, + parse_mode: str = "HTML", +) -> None: + """Render a placeholder message with shared tariffs header.""" + + texts = get_texts(db_user.language) + header = texts.t("ADMIN_TARIFFS_PLACEHOLDER_TITLE", "🧾 Тарифы\n\n") + body = texts.t(text_key, default_text) + + await callback.message.edit_text( + header + body, + reply_markup=get_admin_tariffs_submenu_keyboard(db_user.language), + parse_mode=parse_mode, + ) + await callback.answer() + + +@admin_required +@error_handler +async def show_tariff_mode_activation( + callback: types.CallbackQuery, + db_user: User, + db: AsyncSession, +) -> None: + await _show_placeholder( + callback, + db_user, + "ADMIN_TARIFFS_ACTIVATE_PLACEHOLDER", + ( + "⚙️ Режим тарифов пока в разработке.\n\n" + "После запуска режим заменит слово 'сервера' на 'тарифы' в клиентском интерфейсе" + " и откроет дополнительные настройки продаж." + ), + ) + + +@admin_required +@error_handler +async def show_tariff_creation_placeholder( + callback: types.CallbackQuery, + db_user: User, + db: AsyncSession, +) -> None: + await _show_placeholder( + callback, + db_user, + "ADMIN_TARIFFS_CREATE_PLACEHOLDER", + "➕ Создание тарифов появится здесь. Подготовьте список параметров заранее.", + ) + + +@admin_required +@error_handler +async def show_tariff_list_placeholder( + callback: types.CallbackQuery, + db_user: User, + db: AsyncSession, +) -> None: + await _show_placeholder( + callback, + db_user, + "ADMIN_TARIFFS_LIST_PLACEHOLDER", + "📋 Просмотр тарифов скоро будет доступен. Список покажет активные и скрытые тарифы.", + ) + + +@admin_required +@error_handler +async def show_tariff_stats_placeholder( + callback: types.CallbackQuery, + db_user: User, + db: AsyncSession, +) -> None: + await _show_placeholder( + callback, + db_user, + "ADMIN_TARIFFS_STATS_PLACEHOLDER", + "📊 Статистика тарифов появится здесь и поможет отслеживать продажи по тарифам.", + ) + + +def register_handlers(dp: Dispatcher) -> None: + dp.callback_query.register(show_tariff_mode_activation, F.data == "admin_tariffs_activate") + dp.callback_query.register(show_tariff_creation_placeholder, F.data == "admin_tariffs_create") + dp.callback_query.register(show_tariff_list_placeholder, F.data == "admin_tariffs_list") + dp.callback_query.register(show_tariff_stats_placeholder, F.data == "admin_tariffs_stats") + diff --git a/app/keyboards/admin.py b/app/keyboards/admin.py index ee7729af..bea28080 100644 --- a/app/keyboards/admin.py +++ b/app/keyboards/admin.py @@ -15,6 +15,7 @@ def get_admin_main_keyboard(language: str = "ru") -> InlineKeyboardMarkup: return InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_USERS_SUBSCRIPTIONS", "👥 Юзеры/Подписки"), callback_data="admin_submenu_users")], [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_PROMO_STATS", "💰 Промокоды/Статистика"), callback_data="admin_submenu_promo")], + [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_TARIFFS", "🧾 Тарифы"), callback_data="admin_submenu_tariffs")], [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_SUPPORT", "🛟 Поддержка"), callback_data="admin_submenu_support")], [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_MESSAGES", "📨 Сообщения"), callback_data="admin_submenu_communications")], [InlineKeyboardButton(text=_t(texts, "ADMIN_MAIN_SETTINGS", "⚙️ Настройки"), callback_data="admin_submenu_settings")], @@ -111,6 +112,40 @@ def get_admin_support_submenu_keyboard(language: str = "ru") -> InlineKeyboardMa ]) +def get_admin_tariffs_submenu_keyboard(language: str = "ru") -> InlineKeyboardMarkup: + texts = get_texts(language) + + return InlineKeyboardMarkup(inline_keyboard=[ + [ + InlineKeyboardButton( + text=_t(texts, "ADMIN_TARIFFS_ACTIVATE_BUTTON", "⚙️ Активировать режим тарифов"), + callback_data="admin_tariffs_activate" + ) + ], + [ + InlineKeyboardButton( + text=_t(texts, "ADMIN_TARIFFS_CREATE_BUTTON", "➕ Создать тариф"), + callback_data="admin_tariffs_create" + ) + ], + [ + InlineKeyboardButton( + text=_t(texts, "ADMIN_TARIFFS_LIST_BUTTON", "📋 Список тарифов"), + callback_data="admin_tariffs_list" + ) + ], + [ + InlineKeyboardButton( + text=_t(texts, "ADMIN_TARIFFS_STATS_BUTTON", "📊 Статистика тарифов"), + callback_data="admin_tariffs_stats" + ) + ], + [ + InlineKeyboardButton(text=texts.BACK, callback_data="admin_panel") + ] + ]) + + def get_admin_settings_submenu_keyboard(language: str = "ru") -> InlineKeyboardMarkup: texts = get_texts(language) diff --git a/app/localization/default_locales/en.yml b/app/localization/default_locales/en.yml index 95bb4709..5751a153 100644 --- a/app/localization/default_locales/en.yml +++ b/app/localization/default_locales/en.yml @@ -32,3 +32,16 @@ RULES_TEXT: | 2. Do not distribute spam or malicious content. 3. Respect other community members. +ADMIN_MAIN_TARIFFS: "🧾 Tariffs" +ADMIN_TARIFFS_SUBMENU_TITLE: "🧾 **Tariffs**\\n\\n" +ADMIN_TARIFFS_SUBMENU_DESCRIPTION: "Manage the tariff mode and upcoming features:\\n\\nChoose an action:" +ADMIN_TARIFFS_ACTIVATE_BUTTON: "⚙️ Activate tariff mode" +ADMIN_TARIFFS_CREATE_BUTTON: "➕ Create tariff" +ADMIN_TARIFFS_LIST_BUTTON: "📋 Tariff list" +ADMIN_TARIFFS_STATS_BUTTON: "📊 Tariff statistics" +ADMIN_TARIFFS_PLACEHOLDER_TITLE: "🧾 Tariffs\\n\\n" +ADMIN_TARIFFS_ACTIVATE_PLACEHOLDER: "⚙️ Tariff mode is still under development.\\n\\nOnce launched it will rename 'servers' to 'tariffs' in the client interface and unlock additional sales settings." +ADMIN_TARIFFS_CREATE_PLACEHOLDER: "➕ Tariff creation will appear here. Prepare the parameter list in advance." +ADMIN_TARIFFS_LIST_PLACEHOLDER: "📋 Tariff browsing is coming soon. The list will show both active and hidden tariffs." +ADMIN_TARIFFS_STATS_PLACEHOLDER: "📊 Tariff statistics will appear here to help track sales per tariff." + diff --git a/app/localization/default_locales/ru.yml b/app/localization/default_locales/ru.yml index fc173e56..af23af41 100644 --- a/app/localization/default_locales/ru.yml +++ b/app/localization/default_locales/ru.yml @@ -32,3 +32,16 @@ RULES_TEXT: | 2. Не распространяйте спам и вредоносный контент. 3. Уважайте других пользователей. +ADMIN_MAIN_TARIFFS: "🧾 Тарифы" +ADMIN_TARIFFS_SUBMENU_TITLE: "🧾 **Тарифы**\\n\\n" +ADMIN_TARIFFS_SUBMENU_DESCRIPTION: "Управление тарифным режимом и подготовка функций:\\n\\nВыберите действие:" +ADMIN_TARIFFS_ACTIVATE_BUTTON: "⚙️ Активировать режим тарифов" +ADMIN_TARIFFS_CREATE_BUTTON: "➕ Создать тариф" +ADMIN_TARIFFS_LIST_BUTTON: "📋 Список тарифов" +ADMIN_TARIFFS_STATS_BUTTON: "📊 Статистика тарифов" +ADMIN_TARIFFS_PLACEHOLDER_TITLE: "🧾 Тарифы\\n\\n" +ADMIN_TARIFFS_ACTIVATE_PLACEHOLDER: "⚙️ Режим тарифов пока в разработке.\\n\\nПосле запуска режим заменит слово 'сервера' на 'тарифы' в клиентском интерфейсе и откроет дополнительные настройки продаж." +ADMIN_TARIFFS_CREATE_PLACEHOLDER: "➕ Создание тарифов появится здесь. Подготовьте список параметров заранее." +ADMIN_TARIFFS_LIST_PLACEHOLDER: "📋 Просмотр тарифов скоро будет доступен. Список покажет активные и скрытые тарифы." +ADMIN_TARIFFS_STATS_PLACEHOLDER: "📊 Статистика тарифов появится здесь и поможет отслеживать продажи по тарифам." + diff --git a/app/localization/locales/en.json b/app/localization/locales/en.json index 84750376..d5186a55 100644 --- a/app/localization/locales/en.json +++ b/app/localization/locales/en.json @@ -16,6 +16,18 @@ "COUNTRY_CHANGES_ACTIVE_COUNT": "🌐 Active countries: {count}", "ADMIN_MAIN_MENU": "🏠 Main menu", "ADMIN_CAMPAIGNS": "📣 Promotional campaigns", + "ADMIN_MAIN_TARIFFS": "🧾 Tariffs", + "ADMIN_TARIFFS_SUBMENU_TITLE": "🧾 **Tariffs**\n\n", + "ADMIN_TARIFFS_SUBMENU_DESCRIPTION": "Manage the tariff mode and upcoming features:\n\nChoose an action:", + "ADMIN_TARIFFS_ACTIVATE_BUTTON": "⚙️ Activate tariff mode", + "ADMIN_TARIFFS_CREATE_BUTTON": "➕ Create tariff", + "ADMIN_TARIFFS_LIST_BUTTON": "📋 Tariff list", + "ADMIN_TARIFFS_STATS_BUTTON": "📊 Tariff statistics", + "ADMIN_TARIFFS_PLACEHOLDER_TITLE": "🧾 Tariffs\n\n", + "ADMIN_TARIFFS_ACTIVATE_PLACEHOLDER": "⚙️ Tariff mode is still under development.\n\nOnce launched it will rename 'servers' to 'tariffs' in the client interface and unlock additional sales settings.", + "ADMIN_TARIFFS_CREATE_PLACEHOLDER": "➕ Tariff creation will appear here. Prepare the parameter list in advance.", + "ADMIN_TARIFFS_LIST_PLACEHOLDER": "📋 Tariff browsing is coming soon. The list will show both active and hidden tariffs.", + "ADMIN_TARIFFS_STATS_PLACEHOLDER": "📊 Tariff statistics will appear here to help track sales per tariff.", "AUTOPAY_BUTTON": "💳 Auto payment", "AUTOPAY_SET_DAYS_BUTTON": "⚙️ Configure days", "AUTOPAY_STATUS_ENABLED": "enabled", diff --git a/app/localization/locales/ru.json b/app/localization/locales/ru.json index 4ca51d14..5ea1fc0c 100644 --- a/app/localization/locales/ru.json +++ b/app/localization/locales/ru.json @@ -93,6 +93,18 @@ "ADMIN_PROMO_GROUP_DELETE_CONFIRM": "Удалить промогруппу «{name}»? Все пользователи будут переведены в базовую группу.", "ADMIN_PROMO_GROUP_DELETED": "Промогруппа «{name}» удалена.", "ADMIN_SUBSCRIPTIONS": "📱 Подписки", + "ADMIN_MAIN_TARIFFS": "🧾 Тарифы", + "ADMIN_TARIFFS_SUBMENU_TITLE": "🧾 **Тарифы**\n\n", + "ADMIN_TARIFFS_SUBMENU_DESCRIPTION": "Управление тарифным режимом и подготовка функций:\n\nВыберите действие:", + "ADMIN_TARIFFS_ACTIVATE_BUTTON": "⚙️ Активировать режим тарифов", + "ADMIN_TARIFFS_CREATE_BUTTON": "➕ Создать тариф", + "ADMIN_TARIFFS_LIST_BUTTON": "📋 Список тарифов", + "ADMIN_TARIFFS_STATS_BUTTON": "📊 Статистика тарифов", + "ADMIN_TARIFFS_PLACEHOLDER_TITLE": "🧾 Тарифы\n\n", + "ADMIN_TARIFFS_ACTIVATE_PLACEHOLDER": "⚙️ Режим тарифов пока в разработке.\n\nПосле запуска режим заменит слово 'сервера' на 'тарифы' в клиентском интерфейсе и откроет дополнительные настройки продаж.", + "ADMIN_TARIFFS_CREATE_PLACEHOLDER": "➕ Создание тарифов появится здесь. Подготовьте список параметров заранее.", + "ADMIN_TARIFFS_LIST_PLACEHOLDER": "📋 Просмотр тарифов скоро будет доступен. Список покажет активные и скрытые тарифы.", + "ADMIN_TARIFFS_STATS_PLACEHOLDER": "📊 Статистика тарифов появится здесь и поможет отслеживать продажи по тарифам.", "ADMIN_USERS": "👥 Пользователи", "ADMIN_TICKETS_TITLE_OPEN": "🎫 Открытые тикеты поддержки:", "ADMIN_TICKETS_TITLE_CLOSED": "🎫 Закрытые тикеты поддержки:",