diff --git a/app/handlers/admin/promo_groups.py b/app/handlers/admin/promo_groups.py
index d21b9249..414bed79 100644
--- a/app/handlers/admin/promo_groups.py
+++ b/app/handlers/admin/promo_groups.py
@@ -3,6 +3,7 @@ from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from typing import Dict, Optional, Tuple
from aiogram import Dispatcher, types, F
+from aiogram.exceptions import TelegramBadRequest
from aiogram.fsm.context import FSMContext
from sqlalchemy.ext.asyncio import AsyncSession
@@ -28,29 +29,44 @@ from app.utils.pricing_utils import format_period_description
logger = logging.getLogger(__name__)
-def _format_discount_line(texts, group) -> str:
- return texts.t(
- "ADMIN_PROMO_GROUPS_DISCOUNTS",
- "Скидки — серверы: {servers}%, трафик: {traffic}%, устройства: {devices}%",
- ).format(
- servers=group.server_discount_percent,
- traffic=group.traffic_discount_percent,
- devices=group.device_discount_percent,
+def _format_discount_lines(texts, group) -> Tuple[str, ...]:
+ header = texts.t(
+ "ADMIN_PROMO_GROUP_DISCOUNTS_HEADER",
+ "💸 Размер скидок",
)
+ servers_line = texts.t(
+ "ADMIN_PROMO_GROUP_DISCOUNTS_SERVERS",
+ "• Серверы: {percent}%",
+ ).format(percent=group.server_discount_percent)
+
+ traffic_line = texts.t(
+ "ADMIN_PROMO_GROUP_DISCOUNTS_TRAFFIC",
+ "• Трафик: {percent}%",
+ ).format(percent=group.traffic_discount_percent)
+
+ devices_line = texts.t(
+ "ADMIN_PROMO_GROUP_DISCOUNTS_DEVICES",
+ "• Устройства: {percent}%",
+ ).format(percent=group.device_discount_percent)
+
+ return header, servers_line, traffic_line, devices_line
+
def _format_addon_discounts_line(texts, group: PromoGroup) -> str:
enabled = getattr(group, "apply_discounts_to_addons", True)
- if enabled:
- return texts.t(
- "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_ENABLED",
- "Скидки на доп. услуги: включены",
- )
- return texts.t(
- "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_DISABLED",
- "Скидки на доп. услуги: отключены",
+ status = texts.t(
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_ENABLED"
+ if enabled
+ else "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_DISABLED",
+ "включены" if enabled else "отключены",
)
+ return texts.t(
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNTS_LINE",
+ "• Доп. услуги: {status}",
+ ).format(status=status)
+
def _get_addon_discounts_button_text(texts, group: PromoGroup) -> str:
enabled = getattr(group, "apply_discounts_to_addons", True)
@@ -280,12 +296,10 @@ def _build_edit_menu_content(
"✏️ Настройки промогруппы «{name}»",
).format(name=group.name)
- lines = [
- header,
- _format_discount_line(texts, group),
- _format_addon_discounts_line(texts, group),
- _format_auto_assign_line(texts, group),
- ]
+ lines = [header]
+ lines.extend(_format_discount_lines(texts, group))
+ lines.append(_format_addon_discounts_line(texts, group))
+ lines.append(_format_auto_assign_line(texts, group))
period_lines = _format_period_discounts_lines(texts, group, language)
lines.extend(period_lines)
@@ -394,12 +408,22 @@ async def _send_edit_menu_after_update(
):
menu_text, keyboard = _build_edit_menu_content(texts, group, language)
parts = [part for part in [success_message, menu_text] if part]
+ text = "\n\n".join(parts)
- await message.answer(
- "\n\n".join(parts),
- reply_markup=keyboard,
- parse_mode="HTML",
- )
+ try:
+ await message.edit_text(
+ text,
+ reply_markup=keyboard,
+ parse_mode="HTML",
+ )
+ except TelegramBadRequest as exc:
+ if "message is not modified" in str(exc).lower():
+ return
+ await message.answer(
+ text,
+ reply_markup=keyboard,
+ parse_mode="HTML",
+ )
@admin_required
@@ -431,7 +455,7 @@ async def show_promo_groups_menu(
)
group_lines = [
f"{'⭐' if group.is_default else '🎯'} {group.name}{default_suffix}",
- _format_discount_line(texts, group),
+ "\n".join(_format_discount_lines(texts, group)),
_format_auto_assign_line(texts, group),
texts.t(
"ADMIN_PROMO_GROUPS_MEMBERS_COUNT",
@@ -506,7 +530,7 @@ async def show_promo_group_details(
"ADMIN_PROMO_GROUP_DETAILS_TITLE",
"💳 Промогруппа: {name}",
).format(name=group.name),
- _format_discount_line(texts, group),
+ "\n".join(_format_discount_lines(texts, group)),
_format_auto_assign_line(texts, group),
texts.t(
"ADMIN_PROMO_GROUP_DETAILS_MEMBERS",
@@ -1261,7 +1285,7 @@ async def toggle_promo_group_addon_discounts(
status_text,
)
- await callback.answer()
+ await callback.answer(status_text)
def register_handlers(dp: Dispatcher):
diff --git a/app/localization/locales/en.json b/app/localization/locales/en.json
index e2aa4e2a..56ef19f6 100644
--- a/app/localization/locales/en.json
+++ b/app/localization/locales/en.json
@@ -140,6 +140,13 @@
"ADMIN_PROMO_GROUPS_DISCOUNTS": "Discounts — servers: {servers}%, traffic: {traffic}%, devices: {devices}%",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_ENABLED": "Add-on discounts: enabled",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_DISABLED": "Add-on discounts: disabled",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_HEADER": "💸 Discount overview",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_SERVERS": "• Servers: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_TRAFFIC": "• Traffic: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_DEVICES": "• Devices: {percent}%",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNTS_LINE": "• Add-on services: {status}",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_ENABLED": "enabled",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_DISABLED": "disabled",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_ENABLE": "🧩 Enable add-on discounts",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_DISABLE": "🧩 Disable add-on discounts",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_UPDATED_ENABLED": "Add-on purchase discounts have been enabled.",
diff --git a/app/localization/locales/ru.json b/app/localization/locales/ru.json
index 669987a3..655f82c4 100644
--- a/app/localization/locales/ru.json
+++ b/app/localization/locales/ru.json
@@ -17,6 +17,13 @@
"ADMIN_PROMO_GROUPS_DISCOUNTS": "Скидки — серверы: {servers}%, трафик: {traffic}%, устройства: {devices}%",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_ENABLED": "Скидки на доп. услуги: включены",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_DISABLED": "Скидки на доп. услуги: отключены",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_HEADER": "💸 Размер скидок",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_SERVERS": "• Серверы: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_TRAFFIC": "• Трафик: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_DEVICES": "• Устройства: {percent}%",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNTS_LINE": "• Доп. услуги: {status}",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_ENABLED": "включены",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_DISABLED": "отключены",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_ENABLE": "🧩 Включить скидки на доп. услуги",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_DISABLE": "🧩 Отключить скидки на доп. услуги",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_UPDATED_ENABLED": "Скидки на докупку доп. услуг включены.",
diff --git a/locales/en.json b/locales/en.json
index 110c9ae9..e0fe550c 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -153,6 +153,13 @@
"ADMIN_PROMO_GROUPS_DISCOUNTS": "Discounts — servers: {servers}%, traffic: {traffic}%, devices: {devices}%",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_ENABLED": "Add-on discounts: enabled",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_DISABLED": "Add-on discounts: disabled",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_HEADER": "💸 Discount overview",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_SERVERS": "• Servers: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_TRAFFIC": "• Traffic: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_DEVICES": "• Devices: {percent}%",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNTS_LINE": "• Add-on services: {status}",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_ENABLED": "enabled",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_DISABLED": "disabled",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_ENABLE": "🧩 Enable add-on discounts",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_DISABLE": "🧩 Disable add-on discounts",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_UPDATED_ENABLED": "Add-on purchase discounts have been enabled.",
diff --git a/locales/ru.json b/locales/ru.json
index 51eab11b..9e132fe5 100644
--- a/locales/ru.json
+++ b/locales/ru.json
@@ -19,6 +19,13 @@
"ADMIN_PROMO_GROUPS_DISCOUNTS": "Скидки — серверы: {servers}%, трафик: {traffic}%, устройства: {devices}%",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_ENABLED": "Скидки на доп. услуги: включены",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_DISABLED": "Скидки на доп. услуги: отключены",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_HEADER": "💸 Размер скидок",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_SERVERS": "• Серверы: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_TRAFFIC": "• Трафик: {percent}%",
+ "ADMIN_PROMO_GROUP_DISCOUNTS_DEVICES": "• Устройства: {percent}%",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNTS_LINE": "• Доп. услуги: {status}",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_ENABLED": "включены",
+ "ADMIN_PROMO_GROUP_ADDON_DISCOUNT_STATUS_DISABLED": "отключены",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_ENABLE": "🧩 Включить скидки на доп. услуги",
"ADMIN_PROMO_GROUP_TOGGLE_ADDON_DISCOUNT_DISABLE": "🧩 Отключить скидки на доп. услуги",
"ADMIN_PROMO_GROUP_ADDON_DISCOUNT_UPDATED_ENABLED": "Скидки на докупку доп. услуг включены.",