Update campaign_service.py

This commit is contained in:
Egor
2026-01-17 05:02:54 +03:00
committed by GitHub
parent 73e4009c35
commit cd6f9a3296

View File

@@ -11,6 +11,7 @@ from app.database.crud.subscription import (
get_subscription_by_user_id,
)
from app.database.crud.user import add_user_balance
from app.database.crud.tariff import get_tariff_by_id
from app.database.models import AdvertisingCampaign, User
from app.services.subscription_service import SubscriptionService
@@ -26,6 +27,10 @@ class CampaignBonusResult:
subscription_traffic_gb: Optional[int] = None
subscription_device_limit: Optional[int] = None
subscription_squads: Optional[List[str]] = None
# Поля для tariff
tariff_id: Optional[int] = None
tariff_name: Optional[str] = None
tariff_duration_days: Optional[int] = None
class AdvertisingCampaignService:
@@ -50,6 +55,12 @@ class AdvertisingCampaignService:
if campaign.is_subscription_bonus:
return await self._apply_subscription_bonus(db, user, campaign)
if campaign.is_none_bonus:
return await self._apply_none_bonus(db, user, campaign)
if campaign.is_tariff_bonus:
return await self._apply_tariff_bonus(db, user, campaign)
logger.error("❌ Неизвестный тип бонуса кампании: %s", campaign.bonus_type)
return CampaignBonusResult(success=False)
@@ -184,3 +195,145 @@ class AdvertisingCampaignService:
subscription_device_limit=device_limit,
subscription_squads=squads,
)
async def _apply_none_bonus(
self,
db: AsyncSession,
user: User,
campaign: AdvertisingCampaign,
) -> CampaignBonusResult:
"""Обычная ссылка без награды - только регистрация для отслеживания."""
await record_campaign_registration(
db,
campaign_id=campaign.id,
user_id=user.id,
bonus_type="none",
)
logger.info(
"📊 Пользователь %s зарегистрирован по ссылке кампании %s (без награды)",
user.telegram_id,
campaign.id,
)
return CampaignBonusResult(
success=True,
bonus_type="none",
)
async def _apply_tariff_bonus(
self,
db: AsyncSession,
user: User,
campaign: AdvertisingCampaign,
) -> CampaignBonusResult:
"""Выдача тарифа на определённое время."""
existing_subscription = await get_subscription_by_user_id(db, user.id)
if existing_subscription:
logger.warning(
"⚠️ У пользователя %s уже есть подписка, бонус тарифа кампании %s пропущен",
user.telegram_id,
campaign.id,
)
return CampaignBonusResult(success=False)
if not campaign.tariff_id:
logger.error(
"❌ Кампания %s не имеет указанного тарифа для выдачи",
campaign.id,
)
return CampaignBonusResult(success=False)
duration_days = campaign.tariff_duration_days or 0
if duration_days <= 0:
logger.error(
"❌ Кампания %s не имеет указанной длительности тарифа",
campaign.id,
)
return CampaignBonusResult(success=False)
# Получаем тариф для извлечения параметров
tariff = await get_tariff_by_id(db, campaign.tariff_id)
if not tariff:
logger.error(
"❌ Тариф %s не найден для кампании %s",
campaign.tariff_id,
campaign.id,
)
return CampaignBonusResult(success=False)
if not tariff.is_active:
logger.warning(
"⚠️ Тариф %s неактивен, бонус кампании %s пропущен",
tariff.id,
campaign.id,
)
return CampaignBonusResult(success=False)
traffic_limit = tariff.traffic_limit_gb
device_limit = tariff.device_limit
squads = list(tariff.allowed_squads or [])
if not squads:
try:
from app.database.crud.server_squad import get_random_trial_squad_uuid
trial_uuid = await get_random_trial_squad_uuid(db)
if trial_uuid:
squads = [trial_uuid]
except Exception as error:
logger.error(
"Не удалось подобрать сквад для тарифа кампании %s: %s",
campaign.id,
error,
)
# Создаём подписку как платную (не trial) с привязкой к тарифу
new_subscription = await create_paid_subscription(
db=db,
user_id=user.id,
duration_days=duration_days,
traffic_limit_gb=traffic_limit or 0,
device_limit=device_limit,
connected_squads=squads,
update_server_counters=True,
is_trial=False, # Это полноценная подписка, не пробная
tariff_id=tariff.id,
)
try:
await self.subscription_service.create_remnawave_user(db, new_subscription)
except Exception as error:
logger.error(
"❌ Ошибка синхронизации RemnaWave для тарифа кампании %s: %s",
campaign.id,
error,
)
await record_campaign_registration(
db,
campaign_id=campaign.id,
user_id=user.id,
bonus_type="tariff",
tariff_id=tariff.id,
tariff_duration_days=duration_days,
)
logger.info(
"🎁 Пользователю %s выдан тариф '%s' по кампании %s на %s дней",
user.telegram_id,
tariff.name,
campaign.id,
duration_days,
)
return CampaignBonusResult(
success=True,
bonus_type="tariff",
tariff_id=tariff.id,
tariff_name=tariff.name,
tariff_duration_days=duration_days,
subscription_traffic_gb=traffic_limit or 0,
subscription_device_limit=device_limit,
subscription_squads=squads,
)