Refine purchase and promo messages

This commit is contained in:
Machka Pasla
2025-07-20 21:04:52 +03:00
parent e2df8a01c8
commit d3bfe774c7
5 changed files with 49 additions and 26 deletions
+8 -11
View File
@@ -170,20 +170,17 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
) )
success_message = _("payment_successful_error_details") success_message = _("payment_successful_error_details")
try:
await bot.send_message(user_id, success_message)
except Exception as e_notify:
logging.error(
f"Failed to send final payment success message to user {user_id}: {e_notify}"
)
config_link = activation_details.get("subscription_url") or _( config_link = activation_details.get("subscription_url") or _(
"config_link_not_available" "config_link_not_available"
) )
details_message = _( details_message = (
"payment_successful_full", success_message
end_date=final_end_date_for_user.strftime("%d.%m.%Y %H:%M:%S"), + "\n\n"
config_link=config_link, + _(
"payment_successful_full",
end_date=final_end_date_for_user.strftime("%d.%m.%Y %H:%M:%S"),
config_link=config_link,
)
) )
details_markup = get_connect_and_main_keyboard( details_markup = get_connect_and_main_keyboard(
user_lang, i18n, settings, config_link user_lang, i18n, settings, config_link
+30 -8
View File
@@ -10,7 +10,11 @@ from config.settings import Settings
from bot.states.user_states import UserPromoStates from bot.states.user_states import UserPromoStates
from bot.services.promo_code_service import PromoCodeService from bot.services.promo_code_service import PromoCodeService
from bot.services.subscription_service import SubscriptionService from bot.services.subscription_service import SubscriptionService
from bot.keyboards.inline.user_keyboards import get_back_to_main_menu_markup from bot.keyboards.inline.user_keyboards import (
get_back_to_main_menu_markup,
get_connect_and_main_keyboard,
)
from datetime import datetime
from bot.middlewares.i18n import JsonI18n from bot.middlewares.i18n import JsonI18n
from .start import send_main_menu from .start import send_main_menu
@@ -126,24 +130,42 @@ async def process_promo_code_input(message: types.Message, state: FSMContext,
code=hcode(code_input.upper())) code=hcode(code_input.upper()))
else: else:
success, response_text_from_service = await promo_code_service.apply_promo_code( success, result = await promo_code_service.apply_promo_code(
session, user.id, code_input, current_lang) session, user.id, code_input, current_lang)
response_to_user_text = response_text_from_service
if success: if success:
await session.commit() await session.commit()
logging.info( logging.info(
f"Promo code '{code_input}' successfully applied for user {user.id}." f"Promo code '{code_input}' successfully applied for user {user.id}."
) )
new_end_date = result if isinstance(result, datetime) else None
active = await subscription_service.get_active_subscription_details(session, user.id)
config_link = active.get("config_link") if active else None
config_link = config_link or _("config_link_not_available")
response_to_user_text = _(
"promo_code_applied_success_full",
end_date=(new_end_date.strftime("%d.%m.%Y %H:%M:%S") if new_end_date else "N/A"),
config_link=config_link,
)
reply_markup = get_connect_and_main_keyboard(
current_lang, i18n, settings, config_link
)
else: else:
await session.rollback() await session.rollback()
logging.info( logging.info(
f"Promo code '{code_input}' application failed for user {user.id}. Reason: {response_text_from_service}" f"Promo code '{code_input}' application failed for user {user.id}. Reason: {result}"
)
response_to_user_text = result
reply_markup = get_back_to_main_menu_markup(
current_lang, i18n
) )
await message.answer(response_to_user_text, await message.answer(
reply_markup=get_back_to_main_menu_markup( response_to_user_text,
current_lang, i18n), reply_markup=reply_markup,
parse_mode="HTML") parse_mode="HTML",
)
await state.clear() await state.clear()
logging.info( logging.info(
f"Promo code input '{code_input}' processing finished for user {message.from_user.id}. State cleared." f"Promo code input '{code_input}' processing finished for user {message.from_user.id}. State cleared."
+9 -7
View File
@@ -1,4 +1,5 @@
import logging import logging
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional, Tuple, Dict from typing import Optional, Tuple, Dict
from aiogram import Bot from aiogram import Bot
@@ -23,9 +24,13 @@ class PromoCodeService:
self.bot = bot self.bot = bot
self.i18n = i18n self.i18n = i18n
async def apply_promo_code(self, session: AsyncSession, user_id: int, async def apply_promo_code(
code_input: str, self,
user_lang: str) -> Tuple[bool, str]: session: AsyncSession,
user_id: int,
code_input: str,
user_lang: str,
) -> Tuple[bool, datetime | str]:
_ = lambda k, **kw: self.i18n.gettext(user_lang, k, **kw) _ = lambda k, **kw: self.i18n.gettext(user_lang, k, **kw)
code_input_upper = code_input.strip().upper() code_input_upper = code_input.strip().upper()
@@ -65,10 +70,7 @@ class PromoCodeService:
code_input_upper, code_input_upper,
bonus_days, bonus_days,
) )
return True, _("promo_code_applied_success", return True, new_end_date
code=code_input_upper,
bonus_days=bonus_days,
new_end_date=new_end_date.strftime('%Y-%m-%d'))
else: else:
logging.error( logging.error(
+1
View File
@@ -59,6 +59,7 @@
"promo_code_already_used_by_user": "You have already used promo code <code>{code}</code>.", "promo_code_already_used_by_user": "You have already used promo code <code>{code}</code>.",
"promo_code_no_active_subscription": "You must have an active subscription to apply this promo code.", "promo_code_no_active_subscription": "You must have an active subscription to apply this promo code.",
"promo_code_applied_success": "✅ Promo code <code>{code}</code> applied successfully!\nYour subscription is extended by {bonus_days} days and is now active until {new_end_date}.", "promo_code_applied_success": "✅ Promo code <code>{code}</code> applied successfully!\nYour subscription is extended by {bonus_days} days and is now active until {new_end_date}.",
"promo_code_applied_success_full": "✅ Promo code applied successfully!\n\nSubscription active until: <b>{end_date}</b>\n\nConnection key:\n<code>{config_link}</code>\n\nTo connect, open the link and follow the instructions 👇",
"error_applying_promo_bonus": "Failed to apply promo bonus. Please try again later or contact support.", "error_applying_promo_bonus": "Failed to apply promo bonus. Please try again later or contact support.",
"promo_input_cancelled_short": "Promo code entry cancelled.", "promo_input_cancelled_short": "Promo code entry cancelled.",
+1
View File
@@ -59,6 +59,7 @@
"promo_code_already_used_by_user": "Вы уже активировали промокод <code>{code}</code>.", "promo_code_already_used_by_user": "Вы уже активировали промокод <code>{code}</code>.",
"promo_code_no_active_subscription": "Для активации этого промокода у вас должна быть активная подписка.", "promo_code_no_active_subscription": "Для активации этого промокода у вас должна быть активная подписка.",
"promo_code_applied_success": "✅ Промокод <code>{code}</code> успешно применен!\nВаша подписка продлена на {bonus_days} дней и теперь активна до {new_end_date}.", "promo_code_applied_success": "✅ Промокод <code>{code}</code> успешно применен!\nВаша подписка продлена на {bonus_days} дней и теперь активна до {new_end_date}.",
"promo_code_applied_success_full": "✅ Промокод успешно применен!\n\nПодписка активна до: <b>{end_date}</b>\n\nКлюч подключения:\n<code>{config_link}</code>\n\nЧтобы подключиться, перейдите по ссылке и следуйте инструкции 👇",
"error_applying_promo_bonus": "Не удалось применить бонус по промокоду. Пожалуйста, попробуйте позже или свяжитесь с поддержкой.", "error_applying_promo_bonus": "Не удалось применить бонус по промокоду. Пожалуйста, попробуйте позже или свяжитесь с поддержкой.",
"promo_input_cancelled_short": "Ввод промокода отменен.", "promo_input_cancelled_short": "Ввод промокода отменен.",