fix(traffic): исправлен баг с бесплатным переключением трафика
При наличии докупленного трафика (например 250 + 10 ГБ = 260 ГБ) система округляла текущий пакет до ближайшего (500 ГБ) и позволяла бесплатно переключиться на него. Исправления: - confirm_switch_traffic: используется базовый трафик для расчёта цены - get_traffic_switch_keyboard: добавлен параметр base_traffic_gb - handle_switch_traffic: показывает информацию о докупленном трафике - execute_switch_traffic: сбрасывает purchased_traffic_gb при переключении
This commit is contained in:
@@ -390,9 +390,15 @@ def get_traffic_switch_keyboard(
|
||||
language: str = "ru",
|
||||
subscription_end_date: datetime = None,
|
||||
discount_percent: int = 0,
|
||||
base_traffic_gb: int = None,
|
||||
) -> InlineKeyboardMarkup:
|
||||
from app.config import settings
|
||||
|
||||
# Если базовый трафик не передан, используем текущий
|
||||
# (для обратной совместимости и случаев без докупленного трафика)
|
||||
if base_traffic_gb is None:
|
||||
base_traffic_gb = current_traffic_gb
|
||||
|
||||
months_multiplier = 1
|
||||
period_text = ""
|
||||
if subscription_end_date:
|
||||
@@ -403,7 +409,8 @@ def get_traffic_switch_keyboard(
|
||||
packages = settings.get_traffic_packages()
|
||||
enabled_packages = [pkg for pkg in packages if pkg['enabled']]
|
||||
|
||||
current_price_per_month = settings.get_traffic_price(current_traffic_gb)
|
||||
# Используем базовый трафик для определения цены текущего пакета
|
||||
current_price_per_month = settings.get_traffic_price(base_traffic_gb)
|
||||
discounted_current_per_month, _ = apply_percentage_discount(
|
||||
current_price_per_month,
|
||||
discount_percent,
|
||||
@@ -422,7 +429,8 @@ def get_traffic_switch_keyboard(
|
||||
price_diff_per_month = discounted_price_per_month - discounted_current_per_month
|
||||
total_price_diff = price_diff_per_month * months_multiplier
|
||||
|
||||
if gb == current_traffic_gb:
|
||||
# Сравниваем с базовым трафиком (без докупленного)
|
||||
if gb == base_traffic_gb:
|
||||
emoji = "✅"
|
||||
action_text = " (текущий)"
|
||||
price_text = ""
|
||||
|
||||
@@ -609,6 +609,10 @@ async def handle_switch_traffic(
|
||||
return
|
||||
|
||||
current_traffic = subscription.traffic_limit_gb
|
||||
# Вычисляем базовый трафик (без докупленного) для корректного расчёта цен
|
||||
purchased_traffic = getattr(subscription, 'purchased_traffic_gb', 0) or 0
|
||||
base_traffic = current_traffic - purchased_traffic
|
||||
|
||||
period_hint_days = _get_period_hint_from_subscription(subscription)
|
||||
traffic_discount_percent = _get_addon_discount_percent_for_user(
|
||||
db_user,
|
||||
@@ -616,18 +620,25 @@ async def handle_switch_traffic(
|
||||
period_hint_days,
|
||||
)
|
||||
|
||||
# Показываем информацию о докупленном трафике, если он есть
|
||||
purchased_info = ""
|
||||
if purchased_traffic > 0:
|
||||
purchased_info = f"\n📦 Базовый пакет: {texts.format_traffic(base_traffic)}\n➕ Докуплено: {texts.format_traffic(purchased_traffic)}"
|
||||
|
||||
await callback.message.edit_text(
|
||||
f"🔄 <b>Переключение лимита трафика</b>\n\n"
|
||||
f"Текущий лимит: {texts.format_traffic(current_traffic)}\n"
|
||||
f"Текущий лимит: {texts.format_traffic(current_traffic)}{purchased_info}\n"
|
||||
f"Выберите новый лимит трафика:\n\n"
|
||||
f"💡 <b>Важно:</b>\n"
|
||||
f"• При увеличении - доплата за разницу\n"
|
||||
f"• При уменьшении - возврат средств не производится",
|
||||
f"• При уменьшении - возврат средств не производится\n"
|
||||
f"• Докупленный трафик будет сброшен",
|
||||
reply_markup=get_traffic_switch_keyboard(
|
||||
current_traffic,
|
||||
db_user.language,
|
||||
subscription.end_date,
|
||||
traffic_discount_percent,
|
||||
base_traffic_gb=base_traffic,
|
||||
),
|
||||
parse_mode="HTML"
|
||||
)
|
||||
@@ -645,11 +656,16 @@ async def confirm_switch_traffic(
|
||||
|
||||
current_traffic = subscription.traffic_limit_gb
|
||||
|
||||
# Вычисляем базовый трафик (без докупленного) для корректного расчёта цены
|
||||
purchased_traffic = getattr(subscription, 'purchased_traffic_gb', 0) or 0
|
||||
base_traffic = current_traffic - purchased_traffic
|
||||
|
||||
if new_traffic_gb == current_traffic:
|
||||
await callback.answer("ℹ️ Лимит трафика не изменился", show_alert=True)
|
||||
return
|
||||
|
||||
old_price_per_month = settings.get_traffic_price(current_traffic)
|
||||
# Используем базовый трафик для определения текущей цены пакета
|
||||
old_price_per_month = settings.get_traffic_price(base_traffic)
|
||||
new_price_per_month = settings.get_traffic_price(new_traffic_gb)
|
||||
|
||||
months_remaining = get_remaining_months(subscription.end_date)
|
||||
@@ -766,6 +782,8 @@ async def execute_switch_traffic(
|
||||
)
|
||||
|
||||
subscription.traffic_limit_gb = new_traffic_gb
|
||||
# Сбрасываем докупленный трафик при переключении пакета
|
||||
subscription.purchased_traffic_gb = 0
|
||||
subscription.updated_at = datetime.utcnow()
|
||||
|
||||
await db.commit()
|
||||
|
||||
@@ -854,8 +854,9 @@ async def handle_ticket_reply(
|
||||
await state.clear()
|
||||
|
||||
# Уведомить админов об ответе пользователя
|
||||
logger.info(f"Attempting to notify admins about ticket reply #{ticket_id}")
|
||||
await notify_admins_about_ticket_reply(ticket, reply_text, db)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding ticket reply: {e}")
|
||||
texts = get_texts(db_user.language)
|
||||
@@ -1020,6 +1021,7 @@ async def notify_admins_about_new_ticket(ticket: Ticket, db: AsyncSession):
|
||||
|
||||
async def notify_admins_about_ticket_reply(ticket: Ticket, reply_text: str, db: AsyncSession):
|
||||
"""Уведомить админов об ответе пользователя на тикет"""
|
||||
logger.info(f"notify_admins_about_ticket_reply called for ticket #{ticket.id}")
|
||||
try:
|
||||
from app.config import settings
|
||||
if not settings.is_admin_notifications_enabled():
|
||||
@@ -1059,7 +1061,8 @@ async def notify_admins_about_ticket_reply(ticket: Ticket, reply_text: str, db:
|
||||
return
|
||||
|
||||
service = AdminNotificationService(bot)
|
||||
await service.send_ticket_event_notification(notification_text, None)
|
||||
result = await service.send_ticket_event_notification(notification_text, None)
|
||||
logger.info(f"Ticket #{ticket.id} reply notification sent: {result}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error notifying admins about ticket reply: {e}")
|
||||
|
||||
|
||||
@@ -1510,6 +1510,7 @@ class AdminNotificationService:
|
||||
except Exception:
|
||||
runtime_enabled = True
|
||||
if not (self._is_enabled() and runtime_enabled):
|
||||
logger.info(f"Ticket notification skipped: _is_enabled={self._is_enabled()}, runtime_enabled={runtime_enabled}")
|
||||
return False
|
||||
return await self._send_message(text, reply_markup=keyboard, ticket_event=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user