feat: update tariff UI and mini app
This commit is contained in:
@@ -2205,6 +2205,14 @@ def _serialize_subscription(
|
||||
"traffic_used": _format_bytes(active.get("traffic_used_bytes")),
|
||||
"traffic_limit_bytes": _coerce_int_or_none(active.get("traffic_limit_bytes")),
|
||||
"traffic_used_bytes": _coerce_int_or_none(active.get("traffic_used_bytes")),
|
||||
"tariff_key": active.get("tariff_key"),
|
||||
"tariff_name": active.get("tariff_name"),
|
||||
"tariff_description": active.get("tariff_description"),
|
||||
"billing_model": active.get("billing_model"),
|
||||
"tier_baseline_bytes": _coerce_int_or_none(active.get("tier_baseline_bytes")),
|
||||
"topup_balance_bytes": _coerce_int_or_none(active.get("topup_balance_bytes")),
|
||||
"period_start_at": active.get("period_start_at").isoformat() if active.get("period_start_at") else None,
|
||||
"is_throttled": bool(active.get("is_throttled")),
|
||||
"auto_renew_enabled": bool(getattr(local_sub, "auto_renew_enabled", False)),
|
||||
"provider": getattr(local_sub, "provider", None),
|
||||
}
|
||||
@@ -2217,6 +2225,34 @@ def _serialize_plans(
|
||||
subscription_options: Optional[Dict[int, float]] = None,
|
||||
stars_subscription_options: Optional[Dict[int, int]] = None,
|
||||
) -> List[Dict[str, Any]]:
|
||||
if settings.tariffs_config:
|
||||
plans: List[Dict[str, Any]] = []
|
||||
for tariff in settings.tariffs_config.enabled_tariffs:
|
||||
item: Dict[str, Any] = {
|
||||
"tariff_key": tariff.key,
|
||||
"billing_model": tariff.billing_model,
|
||||
"title": tariff.name(lang),
|
||||
"description": tariff.description(lang),
|
||||
"squad_uuids": tariff.squad_uuids,
|
||||
}
|
||||
if tariff.billing_model == "period":
|
||||
item["periods"] = [
|
||||
{
|
||||
"months": int(months),
|
||||
"price": tariff.period_price(int(months), "rub"),
|
||||
"stars_price": tariff.period_price(int(months), "stars"),
|
||||
}
|
||||
for months in tariff.enabled_periods
|
||||
]
|
||||
item["monthly_gb"] = tariff.monthly_gb
|
||||
else:
|
||||
item["traffic_packages"] = [
|
||||
{"gb": package.gb, "price": package.price}
|
||||
for package in (tariff.traffic_packages.rub if tariff.traffic_packages else [])
|
||||
]
|
||||
plans.append(item)
|
||||
return plans
|
||||
|
||||
active_subscription_options = subscription_options or settings.subscription_options
|
||||
active_stars_subscription_options = stars_subscription_options or settings.stars_subscription_options
|
||||
plans: List[Dict[str, Any]] = []
|
||||
|
||||
@@ -67,20 +67,23 @@ def format_payment_text(payment: Payment, i18n: JsonI18n, lang: str, settings: S
|
||||
'platega': 'Platega',
|
||||
}.get(payment.provider, payment.provider or 'Unknown')
|
||||
|
||||
traffic_mode = getattr(settings, "traffic_sale_mode", False)
|
||||
if traffic_mode:
|
||||
traffic_val = payment.subscription_duration_months or 0
|
||||
sale_base = (payment.sale_mode or "").split("@", 1)[0].split("|", 1)[0]
|
||||
traffic_like = sale_base in {"traffic", "traffic_package", "topup"}
|
||||
if traffic_like:
|
||||
traffic_val = payment.purchased_gb or payment.subscription_duration_months or 0
|
||||
traffic_display = str(int(traffic_val)) if float(traffic_val).is_integer() else f"{traffic_val:g}"
|
||||
period_line = _("admin_payment_traffic_label", traffic_gb=traffic_display)
|
||||
else:
|
||||
period_line = _("admin_payment_months_label", months=payment.subscription_duration_months or 0)
|
||||
tariff_line = f"\nTariff: {payment.tariff_key}" if payment.tariff_key else ""
|
||||
sale_line = f"\nSale mode: {payment.sale_mode}" if payment.sale_mode else ""
|
||||
|
||||
return (
|
||||
f"{status_emoji} <b>{payment.amount} {payment.currency}</b>\n"
|
||||
f"👤 {user_info}\n"
|
||||
f"💳 {provider_text}\n"
|
||||
f"📅 {payment_date}\n"
|
||||
f"{period_line}\n"
|
||||
f"{period_line}{tariff_line}{sale_line}\n"
|
||||
f"📋 {payment.status}\n"
|
||||
f"📝 {payment.description or 'N/A'}"
|
||||
)
|
||||
@@ -212,20 +215,21 @@ async def export_payments_csv_handler(callback: types.CallbackQuery, i18n_data:
|
||||
_("admin_csv_status"),
|
||||
_("admin_csv_description"),
|
||||
_("admin_csv_units"),
|
||||
"sale_mode",
|
||||
"tariff_key",
|
||||
"purchased_gb",
|
||||
_("admin_csv_created_at"),
|
||||
_("admin_csv_provider_payment_id")
|
||||
])
|
||||
|
||||
traffic_mode = getattr(settings, "traffic_sale_mode", False)
|
||||
|
||||
# Write payment data
|
||||
for payment in all_payments:
|
||||
units_val = payment.subscription_duration_months or ""
|
||||
if traffic_mode and units_val not in ("", None):
|
||||
units_val = payment.purchased_gb or payment.subscription_duration_months or ""
|
||||
if (payment.purchased_gb is not None) and units_val not in ("", None):
|
||||
try:
|
||||
units_val = str(int(units_val)) if float(units_val).is_integer() else f"{units_val:g}"
|
||||
except Exception:
|
||||
units_val = payment.subscription_duration_months or ""
|
||||
units_val = payment.purchased_gb or payment.subscription_duration_months or ""
|
||||
writer.writerow([
|
||||
payment.payment_id,
|
||||
payment.user_id,
|
||||
@@ -237,6 +241,9 @@ async def export_payments_csv_handler(callback: types.CallbackQuery, i18n_data:
|
||||
payment.status,
|
||||
payment.description or "",
|
||||
units_val,
|
||||
payment.sale_mode or "",
|
||||
payment.tariff_key or "",
|
||||
payment.purchased_gb or "",
|
||||
payment.created_at.strftime('%Y-%m-%d %H:%M:%S') if payment.created_at else "",
|
||||
payment.provider_payment_id or ""
|
||||
])
|
||||
|
||||
@@ -13,6 +13,10 @@ from bot.keyboards.inline.user_keyboards import (
|
||||
get_subscription_options_keyboard,
|
||||
get_back_to_main_menu_markup,
|
||||
get_autorenew_confirm_keyboard,
|
||||
get_tariff_catalog_keyboard,
|
||||
get_tariff_periods_keyboard,
|
||||
get_tariff_packages_keyboard,
|
||||
get_payment_method_keyboard,
|
||||
)
|
||||
from bot.services.subscription_service import SubscriptionService
|
||||
from bot.services.panel_api_service import PanelApiService
|
||||
@@ -57,6 +61,21 @@ async def display_subscription_options(event: Union[types.Message, types.Callbac
|
||||
return
|
||||
|
||||
currency_symbol_val = settings.DEFAULT_CURRENCY_SYMBOL
|
||||
tariffs_config = getattr(settings, "tariffs_config", None)
|
||||
if tariffs_config:
|
||||
text_content = get_text("select_subscription_period")
|
||||
reply_markup = get_tariff_catalog_keyboard(tariffs_config.enabled_tariffs, current_lang, i18n)
|
||||
target_message_obj = event.message if isinstance(event, types.CallbackQuery) else event
|
||||
if isinstance(event, types.CallbackQuery):
|
||||
try:
|
||||
await target_message_obj.edit_text(text_content, reply_markup=reply_markup)
|
||||
except Exception:
|
||||
await target_message_obj.answer(text_content, reply_markup=reply_markup)
|
||||
await event.answer()
|
||||
else:
|
||||
await target_message_obj.answer(text_content, reply_markup=reply_markup)
|
||||
return
|
||||
|
||||
traffic_packages = getattr(settings, "traffic_packages", {}) or {}
|
||||
stars_traffic_packages = getattr(settings, "stars_traffic_packages", {}) or {}
|
||||
traffic_mode = bool(getattr(settings, "traffic_sale_mode", False) or stars_traffic_packages)
|
||||
@@ -108,6 +127,199 @@ async def reshow_subscription_options_callback(callback: types.CallbackQuery, i1
|
||||
await display_subscription_options(callback, i18n_data, settings, session)
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff:select:"))
|
||||
async def select_tariff_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
get_text = lambda key, **kw: i18n.gettext(current_lang, key, **kw)
|
||||
config = settings.tariffs_config
|
||||
if not config or not callback.message:
|
||||
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
|
||||
return
|
||||
tariff_key = callback.data.split(":", 2)[2]
|
||||
try:
|
||||
tariff = config.require(tariff_key)
|
||||
except Exception:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
return
|
||||
if tariff.billing_model == "period":
|
||||
markup = get_tariff_periods_keyboard(tariff, current_lang, i18n, settings)
|
||||
else:
|
||||
markup = get_tariff_packages_keyboard(tariff, tariff.traffic_packages.rub, current_lang, i18n)
|
||||
text = f"{tariff.name(current_lang)}\n{tariff.description(current_lang)}".strip()
|
||||
await callback.message.edit_text(text, reply_markup=markup)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff:period:"))
|
||||
async def select_tariff_period_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
get_text = lambda key, **kw: i18n.gettext(current_lang, key, **kw)
|
||||
config = settings.tariffs_config
|
||||
if not config or not callback.message:
|
||||
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
|
||||
return
|
||||
_, _, tariff_key, months_raw = callback.data.split(":", 3)
|
||||
tariff = config.require(tariff_key)
|
||||
months = int(months_raw)
|
||||
price_rub = tariff.period_price(months, "rub")
|
||||
stars_price = tariff.period_price(months, "stars")
|
||||
if price_rub is None:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
return
|
||||
markup = get_payment_method_keyboard(
|
||||
months,
|
||||
price_rub,
|
||||
int(stars_price) if stars_price else None,
|
||||
settings.DEFAULT_CURRENCY_SYMBOL,
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
sale_mode=f"subscription@{tariff.key}",
|
||||
)
|
||||
await callback.message.edit_text(get_text("choose_payment_method"), reply_markup=markup)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff:package:"))
|
||||
async def select_tariff_package_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
get_text = lambda key, **kw: i18n.gettext(current_lang, key, **kw)
|
||||
config = settings.tariffs_config
|
||||
if not config or not callback.message:
|
||||
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
|
||||
return
|
||||
_, _, tariff_key, gb_raw = callback.data.split(":", 3)
|
||||
tariff = config.require(tariff_key)
|
||||
gb = float(gb_raw)
|
||||
packages = tariff.traffic_packages.rub if tariff.billing_model == "traffic" else (config.topup_packages_for(tariff).rub if config.topup_packages_for(tariff) else [])
|
||||
package = next((pkg for pkg in packages if float(pkg.gb) == gb), None)
|
||||
if not package:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
return
|
||||
sale_mode = f"{'traffic_package' if tariff.billing_model == 'traffic' else 'topup'}@{tariff.key}"
|
||||
markup = get_payment_method_keyboard(
|
||||
gb,
|
||||
package.price,
|
||||
None,
|
||||
settings.DEFAULT_CURRENCY_SYMBOL,
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
await callback.message.edit_text(get_text("choose_payment_method_traffic"), reply_markup=markup)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data == "tariff_topup:list")
|
||||
async def tariff_topup_list_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, subscription_service: SubscriptionService, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
get_text = lambda key, **kw: i18n.gettext(current_lang, key, **kw)
|
||||
config = settings.tariffs_config
|
||||
active = await subscription_service.get_active_subscription_details(session, callback.from_user.id)
|
||||
if not config or not active or not active.get("tariff_key") or not callback.message:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
return
|
||||
tariff = config.require(active["tariff_key"])
|
||||
packages = config.topup_packages_for(tariff)
|
||||
rub_packages = packages.rub if packages else []
|
||||
if not rub_packages:
|
||||
await callback.answer(get_text("no_subscription_options_available"), show_alert=True)
|
||||
return
|
||||
markup = get_tariff_packages_keyboard(tariff, rub_packages, current_lang, i18n, back_callback="main_action:my_subscription")
|
||||
await callback.message.edit_text(get_text("choose_payment_method_traffic"), reply_markup=markup)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data == "tariff_change:list")
|
||||
async def tariff_change_list_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, subscription_service: SubscriptionService, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
config = settings.tariffs_config
|
||||
active = await subscription_service.get_active_subscription_details(session, callback.from_user.id)
|
||||
if not config or not active or not callback.message:
|
||||
await callback.answer("Error", show_alert=True)
|
||||
return
|
||||
rows = []
|
||||
for tariff in config.enabled_tariffs:
|
||||
if tariff.key == active.get("tariff_key"):
|
||||
continue
|
||||
rows.append([InlineKeyboardButton(text=tariff.name(current_lang), callback_data=f"tariff_change:select:{tariff.key}")])
|
||||
rows.append([InlineKeyboardButton(text=i18n.gettext(current_lang, "back_to_main_menu_button"), callback_data="main_action:my_subscription")])
|
||||
await callback.message.edit_text("Выберите тариф", reply_markup=InlineKeyboardMarkup(inline_keyboard=rows))
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff_change:select:"))
|
||||
async def tariff_change_select_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, subscription_service: SubscriptionService, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
config = settings.tariffs_config
|
||||
if not config or not callback.message:
|
||||
await callback.answer("Error", show_alert=True)
|
||||
return
|
||||
tariff_key = callback.data.split(":", 2)[2]
|
||||
target = config.require(tariff_key)
|
||||
db_sub = await subscription_dal.get_active_subscription_by_user_id(session, callback.from_user.id)
|
||||
if not db_sub:
|
||||
await callback.answer("Error", show_alert=True)
|
||||
return
|
||||
options = subscription_service.calculate_tariff_switch_options(db_sub, target)
|
||||
rows = []
|
||||
if options["mode"] == "period_to_period":
|
||||
rows.append([InlineKeyboardButton(text=f"Без доплаты, дней станет {options['recalc_days']}", callback_data=f"tariff_change:apply:{target.key}:recalc_days")])
|
||||
if options.get("paid_diff_rub", 0) > 0:
|
||||
rows.append([InlineKeyboardButton(text=f"Доплатить {options['paid_diff_rub']} RUB", callback_data=f"tariff_change:pay:{target.key}:{options['paid_diff_rub']}")])
|
||||
elif options["mode"] == "period_to_traffic":
|
||||
rows.append([InlineKeyboardButton(text=f"Перейти без доплаты, получить {options['converted_gb']} GB", callback_data=f"tariff_change:apply:{target.key}:convert_days_to_gb")])
|
||||
for package in target.traffic_packages.rub:
|
||||
rows.append([InlineKeyboardButton(text=f"+ {package.gb:g} GB за {package.price:g} RUB", callback_data=f"tariff:package:{target.key}:{package.gb:g}")])
|
||||
else:
|
||||
for months in target.enabled_periods:
|
||||
price = target.period_price(months, "rub")
|
||||
if price:
|
||||
rows.append([InlineKeyboardButton(text=f"{months} мес. за {price:g} RUB", callback_data=f"tariff:period:{target.key}:{months}")])
|
||||
rows.append([InlineKeyboardButton(text=i18n.gettext(current_lang, "back_to_main_menu_button"), callback_data="tariff_change:list")])
|
||||
await callback.message.edit_text(f"{target.name(current_lang)}\n{target.description(current_lang)}".strip(), reply_markup=InlineKeyboardMarkup(inline_keyboard=rows))
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff_change:apply:"))
|
||||
async def tariff_change_apply_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, subscription_service: SubscriptionService, session: AsyncSession):
|
||||
_, _, tariff_key, mode = callback.data.split(":", 3)
|
||||
result = await subscription_service.switch_tariff_without_payment(session, callback.from_user.id, tariff_key, mode)
|
||||
if result:
|
||||
await session.commit()
|
||||
await callback.answer("Готово", show_alert=True)
|
||||
await my_subscription_command_handler(callback, i18n_data, settings, subscription_service.panel_service, subscription_service, session, callback.bot)
|
||||
else:
|
||||
await callback.answer("Error", show_alert=True)
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("tariff_change:pay:"))
|
||||
async def tariff_change_pay_callback(callback: types.CallbackQuery, i18n_data: dict, settings: Settings, session: AsyncSession):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: JsonI18n = i18n_data.get("i18n_instance")
|
||||
_, _, tariff_key, amount_raw = callback.data.split(":", 3)
|
||||
amount = float(amount_raw)
|
||||
markup = get_payment_method_keyboard(
|
||||
1,
|
||||
amount,
|
||||
None,
|
||||
settings.DEFAULT_CURRENCY_SYMBOL,
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
sale_mode=f"tariff_upgrade@{tariff_key}",
|
||||
)
|
||||
await callback.message.edit_text("Выберите способ оплаты", reply_markup=markup)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
async def my_subscription_command_handler(
|
||||
event: Union[types.Message, types.CallbackQuery],
|
||||
i18n_data: dict,
|
||||
@@ -215,6 +427,11 @@ async def my_subscription_command_handler(
|
||||
config_link=config_link_value,
|
||||
)
|
||||
else:
|
||||
tariff_prefix = ""
|
||||
if active.get("tariff_name"):
|
||||
tariff_prefix = f"🎟 {active.get('tariff_name')}\n"
|
||||
if active.get("tariff_description"):
|
||||
tariff_prefix += f"{active.get('tariff_description')}\n"
|
||||
text = get_text(
|
||||
"my_subscription_details",
|
||||
end_date=end_date.strftime("%Y-%m-%d") if end_date else "N/A",
|
||||
@@ -230,6 +447,8 @@ async def my_subscription_command_handler(
|
||||
),
|
||||
traffic_period=period_label,
|
||||
)
|
||||
if tariff_prefix:
|
||||
text = tariff_prefix + "\n" + text
|
||||
|
||||
base_markup = get_back_to_main_menu_markup(current_lang, i18n)
|
||||
kb = base_markup.inline_keyboard
|
||||
@@ -324,6 +543,12 @@ async def my_subscription_command_handler(
|
||||
InlineKeyboardButton(text=get_text("payment_methods_manage_button"), callback_data="pm:manage")
|
||||
])
|
||||
|
||||
if settings.tariffs_config and local_sub and local_sub.tariff_key:
|
||||
prepend_rows.append([
|
||||
InlineKeyboardButton(text="Сменить тариф", callback_data="tariff_change:list"),
|
||||
InlineKeyboardButton(text="Докупить трафик", callback_data="tariff_topup:list"),
|
||||
])
|
||||
|
||||
if prepend_rows:
|
||||
kb = prepend_rows + kb
|
||||
except Exception:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder, InlineKeyboardButton
|
||||
from aiogram.types import InlineKeyboardMarkup, WebAppInfo
|
||||
from typing import Dict, Optional, List, Tuple
|
||||
from typing import Dict, Optional, List, Tuple, Any
|
||||
|
||||
from config.settings import Settings
|
||||
|
||||
@@ -185,6 +185,54 @@ def get_subscription_options_keyboard(subscription_options: Dict[
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_tariff_catalog_keyboard(tariffs: List[Any], lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
||||
builder = InlineKeyboardBuilder()
|
||||
for tariff in tariffs:
|
||||
label = tariff.name(lang)
|
||||
if tariff.billing_model == "period":
|
||||
min_price = tariff.min_period_price_rub()
|
||||
if min_price is not None:
|
||||
label = f"{label} от {min_price:g}"
|
||||
else:
|
||||
package = tariff.min_traffic_package_rub()
|
||||
if package:
|
||||
label = f"{label} от {package.price:g} / {package.gb:g} GB"
|
||||
builder.row(InlineKeyboardButton(text=label, callback_data=f"tariff:select:{tariff.key}"))
|
||||
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
||||
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="main_action:back_to_main"))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_tariff_periods_keyboard(tariff: Any, lang: str, i18n_instance, settings: Settings) -> InlineKeyboardMarkup:
|
||||
builder = InlineKeyboardBuilder()
|
||||
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
||||
for months in tariff.enabled_periods:
|
||||
rub_price = tariff.period_price(months, "rub")
|
||||
if rub_price and rub_price > 0:
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=_("subscribe_for_months_button", months=months, price=rub_price, currency_symbol=settings.DEFAULT_CURRENCY_SYMBOL),
|
||||
callback_data=f"tariff:period:{tariff.key}:{months}",
|
||||
)
|
||||
)
|
||||
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="main_action:subscribe"))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_tariff_packages_keyboard(tariff: Any, packages: List[Any], lang: str, i18n_instance, back_callback: str = "main_action:subscribe") -> InlineKeyboardMarkup:
|
||||
builder = InlineKeyboardBuilder()
|
||||
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
||||
for package in packages:
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=_("buy_traffic_package_button", traffic_gb=f"{package.gb:g}", price=package.price, currency_symbol="RUB"),
|
||||
callback_data=f"tariff:package:{tariff.key}:{package.gb:g}",
|
||||
)
|
||||
)
|
||||
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data=back_callback))
|
||||
return builder.as_markup()
|
||||
|
||||
|
||||
def get_payment_method_keyboard(months: int, price: float,
|
||||
stars_price: Optional[int],
|
||||
currency_symbol_val: str, lang: str,
|
||||
|
||||
Reference in New Issue
Block a user