feat: group referral bonus display by tariff
This commit is contained in:
@@ -163,32 +163,66 @@ def _legacy_referral_bonus_periods(settings: Settings) -> List[int]:
|
||||
return sorted(int(months) for months in settings.subscription_options)
|
||||
|
||||
|
||||
def _serialize_tariff_period_referral_bonus_details(
|
||||
tariff: Any, lang: str
|
||||
) -> List[Dict[str, Any]]:
|
||||
details: List[Dict[str, Any]] = []
|
||||
for months in sorted(int(month) for month in tariff.enabled_periods):
|
||||
inviter_days = tariff.referral_inviter_bonus_days(months)
|
||||
friend_days = tariff.referral_referee_bonus_days(months)
|
||||
if inviter_days is None and friend_days is None:
|
||||
continue
|
||||
details.append(
|
||||
{
|
||||
"id": f"{tariff.key}:{months}",
|
||||
"tariff_key": tariff.key,
|
||||
"tariff_name": tariff.name(lang),
|
||||
"months": int(months),
|
||||
"title": _format_months_title(int(months), lang),
|
||||
"inviter_days": int(inviter_days or 0),
|
||||
"friend_days": int(friend_days or 0),
|
||||
}
|
||||
)
|
||||
return details
|
||||
|
||||
|
||||
def _serialize_tariff_referral_bonus_details(settings: Settings, lang: str) -> List[Dict[str, Any]]:
|
||||
tariffs_config = settings.tariffs_config
|
||||
if not tariffs_config:
|
||||
return []
|
||||
|
||||
details: List[Dict[str, Any]] = []
|
||||
for tariff in tariffs_config.enabled_tariffs:
|
||||
if tariff.billing_model != "period":
|
||||
period_tariffs = [
|
||||
tariff for tariff in tariffs_config.enabled_tariffs if tariff.billing_model == "period"
|
||||
]
|
||||
if len(period_tariffs) <= 1:
|
||||
return (
|
||||
_serialize_tariff_period_referral_bonus_details(period_tariffs[0], lang)
|
||||
if period_tariffs
|
||||
else []
|
||||
)
|
||||
|
||||
summaries: List[Dict[str, Any]] = []
|
||||
for tariff in period_tariffs:
|
||||
details = _serialize_tariff_period_referral_bonus_details(tariff, lang)
|
||||
if not details:
|
||||
continue
|
||||
for months in sorted(int(month) for month in tariff.enabled_periods):
|
||||
inviter_days = tariff.referral_inviter_bonus_days(months)
|
||||
friend_days = tariff.referral_referee_bonus_days(months)
|
||||
if inviter_days is None and friend_days is None:
|
||||
continue
|
||||
details.append(
|
||||
{
|
||||
"id": f"{tariff.key}:{months}",
|
||||
"tariff_key": tariff.key,
|
||||
"tariff_name": tariff.name(lang),
|
||||
"months": int(months),
|
||||
"title": f"{tariff.name(lang)} - {_format_months_title(int(months), lang)}",
|
||||
"inviter_days": int(inviter_days or 0),
|
||||
"friend_days": int(friend_days or 0),
|
||||
}
|
||||
)
|
||||
return details
|
||||
inviter_values = [int(item["inviter_days"]) for item in details]
|
||||
friend_values = [int(item["friend_days"]) for item in details]
|
||||
summaries.append(
|
||||
{
|
||||
"id": f"tariff:{tariff.key}",
|
||||
"type": "tariff_summary",
|
||||
"tariff_key": tariff.key,
|
||||
"tariff_name": tariff.name(lang),
|
||||
"title": tariff.name(lang),
|
||||
"inviter_min_days": min(inviter_values),
|
||||
"inviter_max_days": max(inviter_values),
|
||||
"friend_min_days": min(friend_values),
|
||||
"friend_max_days": max(friend_values),
|
||||
"details": details,
|
||||
}
|
||||
)
|
||||
return summaries
|
||||
|
||||
|
||||
def _serialize_referral_bonus_details(settings: Settings, lang: str) -> List[Dict[str, Any]]:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import logging
|
||||
from typing import Optional, Union
|
||||
from typing import Any, Callable, Optional, Union
|
||||
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
||||
|
||||
from aiogram import Bot, F, Router, types
|
||||
@@ -76,31 +76,10 @@ async def referral_command_handler(
|
||||
await event.answer()
|
||||
return
|
||||
|
||||
bonus_info_parts = []
|
||||
if getattr(settings, "traffic_sale_mode", False):
|
||||
bonus_details_str = _("referral_not_available_for_traffic")
|
||||
else:
|
||||
if settings.subscription_options:
|
||||
for months_period_key, _price in sorted(settings.subscription_options.items()):
|
||||
inv_bonus = settings.referral_bonus_inviter.get(months_period_key)
|
||||
ref_bonus = settings.referral_bonus_referee.get(months_period_key)
|
||||
if inv_bonus is not None or ref_bonus is not None:
|
||||
bonus_info_parts.append(
|
||||
_(
|
||||
"referral_bonus_per_period",
|
||||
months=months_period_key,
|
||||
inviter_bonus_days=inv_bonus
|
||||
if inv_bonus is not None
|
||||
else _("no_bonus_placeholder"),
|
||||
referee_bonus_days=ref_bonus
|
||||
if ref_bonus is not None
|
||||
else _("no_bonus_placeholder"),
|
||||
)
|
||||
)
|
||||
|
||||
bonus_details_str = (
|
||||
"\n".join(bonus_info_parts) if bonus_info_parts else _("referral_no_bonuses_configured")
|
||||
)
|
||||
bonus_details_str = _build_referral_bonus_details_text(settings, _, current_lang)
|
||||
|
||||
referral_stats = await referral_service.get_referral_stats(session, inviter_user_id)
|
||||
|
||||
@@ -208,6 +187,132 @@ async def referral_action_handler(
|
||||
await callback.answer()
|
||||
|
||||
|
||||
Translator = Callable[..., str]
|
||||
|
||||
|
||||
def _period_bonus_text(
|
||||
translator: Translator,
|
||||
*,
|
||||
months: int,
|
||||
inviter_days: Optional[int],
|
||||
referee_days: Optional[int],
|
||||
) -> str:
|
||||
return translator(
|
||||
"referral_bonus_per_period",
|
||||
months=months,
|
||||
inviter_bonus_days=(
|
||||
inviter_days if inviter_days is not None else translator("no_bonus_placeholder")
|
||||
),
|
||||
referee_bonus_days=(
|
||||
referee_days if referee_days is not None else translator("no_bonus_placeholder")
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _tariff_period_bonus_entries(tariff: Any) -> list[dict[str, Optional[int]]]:
|
||||
entries: list[dict[str, Optional[int]]] = []
|
||||
for months in sorted(int(month) for month in getattr(tariff, "enabled_periods", [])):
|
||||
inviter_days = tariff.referral_inviter_bonus_days(months)
|
||||
referee_days = tariff.referral_referee_bonus_days(months)
|
||||
if inviter_days is None and referee_days is None:
|
||||
continue
|
||||
entries.append(
|
||||
{
|
||||
"months": months,
|
||||
"inviter_days": inviter_days,
|
||||
"referee_days": referee_days,
|
||||
}
|
||||
)
|
||||
return entries
|
||||
|
||||
|
||||
def _legacy_period_bonus_entries(settings: Settings) -> list[dict[str, Optional[int]]]:
|
||||
entries: list[dict[str, Optional[int]]] = []
|
||||
for months, _price in sorted(settings.subscription_options.items()):
|
||||
inviter_days = settings.referral_bonus_inviter.get(months)
|
||||
referee_days = settings.referral_bonus_referee.get(months)
|
||||
if inviter_days is None and referee_days is None:
|
||||
continue
|
||||
entries.append(
|
||||
{
|
||||
"months": int(months),
|
||||
"inviter_days": inviter_days,
|
||||
"referee_days": referee_days,
|
||||
}
|
||||
)
|
||||
return entries
|
||||
|
||||
|
||||
def _bonus_days_range(translator: Translator, values: list[int]) -> str:
|
||||
return translator(
|
||||
"referral_bonus_days_range",
|
||||
min_days=min(values),
|
||||
max_days=max(values),
|
||||
)
|
||||
|
||||
|
||||
def _build_referral_bonus_details_text(
|
||||
settings: Settings, translator: Translator, current_lang: str
|
||||
) -> str:
|
||||
tariffs_config = settings.tariffs_config
|
||||
if not tariffs_config:
|
||||
bonus_info_parts = [
|
||||
_period_bonus_text(
|
||||
translator,
|
||||
months=int(entry["months"] or 0),
|
||||
inviter_days=entry["inviter_days"],
|
||||
referee_days=entry["referee_days"],
|
||||
)
|
||||
for entry in _legacy_period_bonus_entries(settings)
|
||||
]
|
||||
return (
|
||||
"\n".join(bonus_info_parts)
|
||||
if bonus_info_parts
|
||||
else translator("referral_no_bonuses_configured")
|
||||
)
|
||||
|
||||
period_tariffs = [
|
||||
tariff for tariff in tariffs_config.enabled_tariffs if tariff.billing_model == "period"
|
||||
]
|
||||
if len(period_tariffs) <= 1:
|
||||
entries = _tariff_period_bonus_entries(period_tariffs[0]) if period_tariffs else []
|
||||
bonus_info_parts = [
|
||||
_period_bonus_text(
|
||||
translator,
|
||||
months=int(entry["months"] or 0),
|
||||
inviter_days=entry["inviter_days"],
|
||||
referee_days=entry["referee_days"],
|
||||
)
|
||||
for entry in entries
|
||||
]
|
||||
return (
|
||||
"\n".join(bonus_info_parts)
|
||||
if bonus_info_parts
|
||||
else translator("referral_no_bonuses_configured")
|
||||
)
|
||||
|
||||
bonus_info_parts = []
|
||||
for tariff in period_tariffs:
|
||||
entries = _tariff_period_bonus_entries(tariff)
|
||||
if not entries:
|
||||
continue
|
||||
inviter_values = [int(entry["inviter_days"] or 0) for entry in entries]
|
||||
referee_values = [int(entry["referee_days"] or 0) for entry in entries]
|
||||
bonus_info_parts.append(
|
||||
translator(
|
||||
"referral_bonus_tariff_range",
|
||||
tariff_name=tariff.name(current_lang),
|
||||
inviter_bonus_range=_bonus_days_range(translator, inviter_values),
|
||||
referee_bonus_range=_bonus_days_range(translator, referee_values),
|
||||
)
|
||||
)
|
||||
return (
|
||||
"\n".join(bonus_info_parts)
|
||||
if bonus_info_parts
|
||||
else translator("referral_no_bonuses_configured")
|
||||
)
|
||||
|
||||
|
||||
def _build_webapp_referral_link(
|
||||
base_url: Optional[str], referral_code: Optional[str]
|
||||
) -> Optional[str]:
|
||||
|
||||
@@ -1537,6 +1537,89 @@ a {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.referral-tariff-dropdown {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--surface-sheen-soft);
|
||||
}
|
||||
|
||||
.referral-tariff-summary {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
padding: 10px 11px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.referral-tariff-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.referral-tariff-copy {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.referral-tariff-copy strong {
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.referral-tariff-copy small {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.referral-tariff-dropdown summary:hover .premium-server-help-icon,
|
||||
.referral-tariff-dropdown[open] .premium-server-help-icon {
|
||||
color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
||||
}
|
||||
|
||||
.referral-tariff-details {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
padding: 0 8px;
|
||||
opacity: 0;
|
||||
transform: translateY(-2px);
|
||||
transform-origin: top;
|
||||
transition:
|
||||
grid-template-rows 0.22s ease,
|
||||
padding 0.22s ease,
|
||||
opacity 0.18s ease,
|
||||
transform 0.22s ease;
|
||||
}
|
||||
|
||||
.referral-tariff-details > div {
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.referral-tariff-detail-list {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.referral-tariff-dropdown[open] .referral-tariff-details {
|
||||
grid-template-rows: 1fr;
|
||||
padding: 0 8px 8px;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.referral-bonus-row-nested {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
.settings-profile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { Copy, Gift, Ticket, TriangleAlert } from "$components/ui/icons.js";
|
||||
import { CircleQuestionMark, Copy, Gift, Ticket, TriangleAlert } from "$components/ui/icons.js";
|
||||
import { Tooltip } from "$components/ui/primitives.js";
|
||||
|
||||
import Button from "$components/ui/button.svelte";
|
||||
@@ -21,6 +21,17 @@
|
||||
export let clearPromoFieldError = () => {};
|
||||
export let copyText = () => {};
|
||||
export let t = (key) => key;
|
||||
|
||||
$: tariffBonusSummaries = referralBonusDetails.filter((bonus) => Array.isArray(bonus.details));
|
||||
$: periodBonusDetails = referralBonusDetails.filter((bonus) => !Array.isArray(bonus.details));
|
||||
$: usesTariffBonusSummaries = tariffBonusSummaries.length > 0;
|
||||
|
||||
function daysRange(minDays, maxDays) {
|
||||
return t("wa_referral_bonus_range_days", {
|
||||
min: Number(minDays || 0),
|
||||
max: Number(maxDays || 0),
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<main class="content with-nav">
|
||||
@@ -55,20 +66,68 @@
|
||||
<small>{t("wa_referral_bonus_friend_days", { days: referralWelcomeBonusDays })}</small>
|
||||
</div>
|
||||
{/if}
|
||||
{#if referralBonusDetails.length}
|
||||
{#if usesTariffBonusSummaries}
|
||||
<p class="referral-bonus-intro">{t("wa_referral_bonus_depends_on_tariff")}</p>
|
||||
{:else if periodBonusDetails.length}
|
||||
<p class="referral-bonus-intro">{t("wa_referral_bonus_paid_intro")}</p>
|
||||
{/if}
|
||||
{#each referralBonusDetails as bonus, index (bonus.id || `${bonus.tariff_key || "legacy"}:${bonus.months || index}`)}
|
||||
<div class="referral-bonus-row">
|
||||
<strong>{bonus.title || `${bonus.months || "?"}`}</strong>
|
||||
<small
|
||||
>{t("wa_referral_bonus_you_days", { days: Number(bonus.inviter_days || 0) })}</small
|
||||
>
|
||||
<small
|
||||
>{t("wa_referral_bonus_friend_days", { days: Number(bonus.friend_days || 0) })}</small
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
{#if usesTariffBonusSummaries}
|
||||
{#each tariffBonusSummaries as tariffBonus, index (tariffBonus.id || `tariff:${tariffBonus.tariff_key || index}`)}
|
||||
<details class="referral-tariff-dropdown">
|
||||
<summary class="referral-tariff-summary">
|
||||
<span class="referral-tariff-copy">
|
||||
<strong>{tariffBonus.title || tariffBonus.tariff_name}</strong>
|
||||
<small>
|
||||
{t("wa_referral_bonus_you_range", {
|
||||
range: daysRange(tariffBonus.inviter_min_days, tariffBonus.inviter_max_days),
|
||||
})}
|
||||
</small>
|
||||
<small>
|
||||
{t("wa_referral_bonus_friend_range", {
|
||||
range: daysRange(tariffBonus.friend_min_days, tariffBonus.friend_max_days),
|
||||
})}
|
||||
</small>
|
||||
</span>
|
||||
<CircleQuestionMark class="premium-server-help-icon" size={16} />
|
||||
</summary>
|
||||
<div class="referral-tariff-details">
|
||||
<div class="referral-tariff-detail-list">
|
||||
{#each tariffBonus.details || [] as bonus, detailIndex (bonus.id || `${tariffBonus.tariff_key || index}:${bonus.months || detailIndex}`)}
|
||||
<div class="referral-bonus-row referral-bonus-row-nested">
|
||||
<strong>{bonus.title || `${bonus.months || "?"}`}</strong>
|
||||
<small
|
||||
>{t("wa_referral_bonus_you_days", {
|
||||
days: Number(bonus.inviter_days || 0),
|
||||
})}</small
|
||||
>
|
||||
<small
|
||||
>{t("wa_referral_bonus_friend_days", {
|
||||
days: Number(bonus.friend_days || 0),
|
||||
})}</small
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each periodBonusDetails as bonus, index (bonus.id || `${bonus.tariff_key || "legacy"}:${bonus.months || index}`)}
|
||||
<div class="referral-bonus-row">
|
||||
<strong>{bonus.title || `${bonus.months || "?"}`}</strong>
|
||||
<small
|
||||
>{t("wa_referral_bonus_you_days", {
|
||||
days: Number(bonus.inviter_days || 0),
|
||||
})}</small
|
||||
>
|
||||
<small
|
||||
>{t("wa_referral_bonus_friend_days", {
|
||||
days: Number(bonus.friend_days || 0),
|
||||
})}</small
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<StatusMessage>{t("wa_referral_bonus_not_configured")}</StatusMessage>
|
||||
|
||||
@@ -97,6 +97,8 @@
|
||||
"no_button": "No",
|
||||
"referral_program_info_new": "🎁 <b>Referral Program</b>\n\n📊 <b>Your stats:</b>\n👥 Friends invited: <b>{invited_count}</b>\n💳 Purchased subscription: <b>{purchased_count}</b>\n\n🔗 Telegram link:\n<code>{referral_link}</code>{webapp_link_section}\n\n💰 <b>Invitation bonuses:</b>\n{bonus_details}\n\n📢 Share the link with friends and get bonuses!",
|
||||
"referral_bonus_per_period": "\n\n🎁 For a friend's {months}-month subscription:\n ➢ You: <b>{inviter_bonus_days} days</b>\n ➢ Friend: <b>{referee_bonus_days} days</b>",
|
||||
"referral_bonus_days_range": "from {min_days} to {max_days} days",
|
||||
"referral_bonus_tariff_range": "\n\n🎁 {tariff_name}:\n ➢ You: <b>{inviter_bonus_range}</b>\n ➢ Friend: <b>{referee_bonus_range}</b>",
|
||||
"referral_not_available_for_traffic": "Referral bonuses are not available for traffic packages.",
|
||||
"referral_share_message_button": "📩 Message for friend",
|
||||
"referral_friend_message": "🚀 Hey! Try this service - it's fast, reliable and affordable!\n\n🎁 Use my link to get bonus days with your subscription!\n\n{referral_link}",
|
||||
@@ -778,8 +780,12 @@
|
||||
"wa_referral_bonus_once_note": "Bonus is granted only once per invited user after their first payment.",
|
||||
"wa_referral_bonus_registration_title": "For registration via referral link",
|
||||
"wa_referral_bonus_paid_intro": "If a friend pays for a subscription:",
|
||||
"wa_referral_bonus_depends_on_tariff": "Bonus depends on the tariff and payment period your friend chooses",
|
||||
"wa_referral_bonus_range_days": "from {min} to {max} days",
|
||||
"wa_referral_bonus_you_days": "You: +{days} days",
|
||||
"wa_referral_bonus_friend_days": "Friend: +{days} days",
|
||||
"wa_referral_bonus_you_range": "You: {range}",
|
||||
"wa_referral_bonus_friend_range": "Friend: {range}",
|
||||
"wa_referral_bonus_not_configured": "Referral bonuses are not configured",
|
||||
"wa_promo_enter": "Enter promo code",
|
||||
"wa_promo_activated_until": "Promo code activated. Subscription until {date}",
|
||||
|
||||
@@ -97,6 +97,8 @@
|
||||
"no_button": "Нет",
|
||||
"referral_program_info_new": "🎁 <b>Реферальная программа</b>\n\n📊 <b>Твоя статистика:</b>\n👥 Приглашено друзей: <b>{invited_count}</b>\n💳 Купили подписку: <b>{purchased_count}</b>\n\n🔗 Telegram ссылка:\n<code>{referral_link}</code>{webapp_link_section}\n\n💰 <b>Бонусы за приглашения:</b>\n{bonus_details}\n\n📢 Поделись ссылкой с друзьями и получай бонусы!",
|
||||
"referral_bonus_per_period": "\n\n🎁 За {months}-мес. подписку друга:\n ➢ Вы: <b>{inviter_bonus_days} дн.</b>\n ➢ Друг: <b>{referee_bonus_days} дн.</b>",
|
||||
"referral_bonus_days_range": "от {min_days} до {max_days} дн.",
|
||||
"referral_bonus_tariff_range": "\n\n🎁 {tariff_name}:\n ➢ Вы: <b>{inviter_bonus_range}</b>\n ➢ Друг: <b>{referee_bonus_range}</b>",
|
||||
"referral_not_available_for_traffic": "Для пакетов трафика реферальные бонусы не начисляются.",
|
||||
"referral_share_message_button": "📩 Сообщение для друга",
|
||||
"referral_friend_message": "🚀 Привет! Попробуй этот сервис - быстрый, надёжный и доступный!\n\n🎁 По моей ссылке тебе дадут бонусные дни к подписке!\n\n{referral_link}",
|
||||
@@ -778,8 +780,12 @@
|
||||
"wa_referral_bonus_once_note": "Бонус за приглашённого начисляется только один раз, после его первой оплаты.",
|
||||
"wa_referral_bonus_registration_title": "За регистрацию по реферальной ссылке",
|
||||
"wa_referral_bonus_paid_intro": "Если друг оплатит подписку:",
|
||||
"wa_referral_bonus_depends_on_tariff": "Бонус зависит от тарифа и периода оплаты друга",
|
||||
"wa_referral_bonus_range_days": "от {min} до {max} дней",
|
||||
"wa_referral_bonus_you_days": "Вам: +{days} дней",
|
||||
"wa_referral_bonus_friend_days": "Другу: +{days} дней",
|
||||
"wa_referral_bonus_you_range": "Вам: {range}",
|
||||
"wa_referral_bonus_friend_range": "Другу: {range}",
|
||||
"wa_referral_bonus_not_configured": "Реферальные бонусы не настроены",
|
||||
"wa_promo_enter": "Введите промокод",
|
||||
"wa_promo_activated_until": "Промокод активирован. Подписка до {date}",
|
||||
|
||||
@@ -20,6 +20,7 @@ from bot.keyboards.inline.user_keyboards import (
|
||||
payment_methods_back_callback,
|
||||
payment_options_back_callback,
|
||||
)
|
||||
from config.tariffs_config import TariffsConfig
|
||||
|
||||
|
||||
class JsonI18nStub:
|
||||
@@ -304,3 +305,95 @@ class UserBotMenuTests(unittest.TestCase):
|
||||
|
||||
self.assertLess(text.index("Telegram link:"), text.index("Web link:"))
|
||||
self.assertLess(text.index("Web link:"), text.index("Invitation bonuses:"))
|
||||
|
||||
def test_single_tariff_referral_text_uses_period_rows_without_tariff_name(self):
|
||||
settings = SimpleNamespace(
|
||||
tariffs_config=TariffsConfig.model_validate(
|
||||
{
|
||||
"default_tariff": "standard",
|
||||
"tariffs": [
|
||||
{
|
||||
"key": "standard",
|
||||
"names": {"en": "Standard"},
|
||||
"descriptions": {},
|
||||
"squad_uuids": ["standard"],
|
||||
"billing_model": "period",
|
||||
"monthly_gb": 100,
|
||||
"prices_rub": {"2": 400, "4": 800},
|
||||
"prices_stars": {},
|
||||
"referral_bonus_days_inviter": {"2": 5, "4": 10},
|
||||
"referral_bonus_days_referee": {"2": 1, "4": 2},
|
||||
"enabled_periods": [2, 4],
|
||||
"enabled": True,
|
||||
}
|
||||
],
|
||||
}
|
||||
),
|
||||
subscription_options={},
|
||||
referral_bonus_inviter={},
|
||||
referral_bonus_referee={},
|
||||
)
|
||||
|
||||
text = referral._build_referral_bonus_details_text(
|
||||
settings,
|
||||
lambda key, **kwargs: self.i18n.gettext("en", key, **kwargs),
|
||||
"en",
|
||||
)
|
||||
|
||||
self.assertIn("For a friend's 2-month subscription", text)
|
||||
self.assertIn("For a friend's 4-month subscription", text)
|
||||
self.assertNotIn("Standard", text)
|
||||
|
||||
def test_multiple_tariff_referral_text_uses_tariff_ranges(self):
|
||||
settings = SimpleNamespace(
|
||||
tariffs_config=TariffsConfig.model_validate(
|
||||
{
|
||||
"default_tariff": "standard",
|
||||
"tariffs": [
|
||||
{
|
||||
"key": "standard",
|
||||
"names": {"en": "Standard"},
|
||||
"descriptions": {},
|
||||
"squad_uuids": ["standard"],
|
||||
"billing_model": "period",
|
||||
"monthly_gb": 100,
|
||||
"prices_rub": {"2": 400, "4": 800},
|
||||
"prices_stars": {},
|
||||
"referral_bonus_days_inviter": {"2": 5, "4": 10},
|
||||
"referral_bonus_days_referee": {"2": 1, "4": 2},
|
||||
"enabled_periods": [2, 4],
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"key": "premium",
|
||||
"names": {"en": "Premium"},
|
||||
"descriptions": {},
|
||||
"squad_uuids": ["premium"],
|
||||
"billing_model": "period",
|
||||
"monthly_gb": 500,
|
||||
"prices_rub": {"1": 700, "3": 1800},
|
||||
"prices_stars": {},
|
||||
"referral_bonus_days_inviter": {"1": 8, "3": 24},
|
||||
"referral_bonus_days_referee": {"1": 3, "3": 9},
|
||||
"enabled_periods": [1, 3],
|
||||
"enabled": True,
|
||||
},
|
||||
],
|
||||
}
|
||||
),
|
||||
subscription_options={},
|
||||
referral_bonus_inviter={},
|
||||
referral_bonus_referee={},
|
||||
)
|
||||
|
||||
text = referral._build_referral_bonus_details_text(
|
||||
settings,
|
||||
lambda key, **kwargs: self.i18n.gettext("en", key, **kwargs),
|
||||
"en",
|
||||
)
|
||||
|
||||
self.assertIn("Standard", text)
|
||||
self.assertIn("Premium", text)
|
||||
self.assertIn("from 5 to 10 days", text)
|
||||
self.assertIn("from 8 to 24 days", text)
|
||||
self.assertNotIn("2-month subscription", text)
|
||||
|
||||
@@ -141,7 +141,7 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
|
||||
"tariff_key": "standard",
|
||||
"tariff_name": "Standard",
|
||||
"months": 2,
|
||||
"title": "Standard - 2 months",
|
||||
"title": "2 months",
|
||||
"inviter_days": 5,
|
||||
"friend_days": 1,
|
||||
},
|
||||
@@ -150,7 +150,7 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
|
||||
"tariff_key": "standard",
|
||||
"tariff_name": "Standard",
|
||||
"months": 4,
|
||||
"title": "Standard - 4 months",
|
||||
"title": "4 months",
|
||||
"inviter_days": 10,
|
||||
"friend_days": 2,
|
||||
},
|
||||
@@ -159,7 +159,7 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
|
||||
"tariff_key": "standard",
|
||||
"tariff_name": "Standard",
|
||||
"months": 8,
|
||||
"title": "Standard - 8 months",
|
||||
"title": "8 months",
|
||||
"inviter_days": 0,
|
||||
"friend_days": 4,
|
||||
},
|
||||
@@ -168,13 +168,78 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
|
||||
"tariff_key": "standard",
|
||||
"tariff_name": "Standard",
|
||||
"months": 16,
|
||||
"title": "Standard - 16 months",
|
||||
"title": "16 months",
|
||||
"inviter_days": 40,
|
||||
"friend_days": 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
def test_referral_bonus_details_group_multiple_tariffs(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
path = Path(tmpdir) / "tariffs.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"default_tariff": "standard",
|
||||
"tariffs": [
|
||||
{
|
||||
"key": "standard",
|
||||
"names": {"en": "Standard"},
|
||||
"descriptions": {},
|
||||
"squad_uuids": ["standard"],
|
||||
"billing_model": "period",
|
||||
"monthly_gb": 100,
|
||||
"prices_rub": {"2": 400, "4": 800},
|
||||
"prices_stars": {},
|
||||
"referral_bonus_days_inviter": {"2": 5, "4": 10},
|
||||
"referral_bonus_days_referee": {"2": 1, "4": 2},
|
||||
"enabled_periods": [2, 4],
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"key": "premium",
|
||||
"names": {"en": "Premium"},
|
||||
"descriptions": {},
|
||||
"squad_uuids": ["premium"],
|
||||
"billing_model": "period",
|
||||
"monthly_gb": 500,
|
||||
"prices_rub": {"1": 700, "3": 1800},
|
||||
"prices_stars": {},
|
||||
"referral_bonus_days_inviter": {"1": 8, "3": 24},
|
||||
"referral_bonus_days_referee": {"1": 3, "3": 9},
|
||||
"enabled_periods": [1, 3],
|
||||
"enabled": True,
|
||||
},
|
||||
],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
settings = Settings(
|
||||
_env_file=None,
|
||||
BOT_TOKEN="token",
|
||||
POSTGRES_USER="app_user",
|
||||
POSTGRES_PASSWORD="app_password",
|
||||
TARIFFS_CONFIG_PATH=str(path),
|
||||
)
|
||||
|
||||
details = subscription_webapp._serialize_referral_bonus_details(settings, "en")
|
||||
|
||||
self.assertEqual([item["type"] for item in details], ["tariff_summary", "tariff_summary"])
|
||||
self.assertEqual(details[0]["title"], "Standard")
|
||||
self.assertEqual(details[0]["inviter_min_days"], 5)
|
||||
self.assertEqual(details[0]["inviter_max_days"], 10)
|
||||
self.assertEqual(details[0]["friend_min_days"], 1)
|
||||
self.assertEqual(details[0]["friend_max_days"], 2)
|
||||
self.assertEqual(
|
||||
[item["title"] for item in details[0]["details"]],
|
||||
["2 months", "4 months"],
|
||||
)
|
||||
self.assertEqual(details[1]["title"], "Premium")
|
||||
self.assertEqual(details[1]["inviter_min_days"], 8)
|
||||
self.assertEqual(details[1]["inviter_max_days"], 24)
|
||||
|
||||
def test_subscription_template_does_not_block_on_telegram_sdk(self):
|
||||
html = subscription_webapp.TEMPLATE_PATH.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user