diff --git a/app/database/crud/subscription.py b/app/database/crud/subscription.py index e57ffb9f..c33ad8bc 100644 --- a/app/database/crud/subscription.py +++ b/app/database/crud/subscription.py @@ -763,18 +763,26 @@ async def reactivate_subscription(db: AsyncSession, subscription: Subscription) async def get_expiring_subscriptions(db: AsyncSession, days_before: int = 3) -> list[Subscription]: + from app.database.models import Tariff + threshold_date = datetime.now(UTC) + timedelta(days=days_before) result = await db.execute( select(Subscription) .join(User, Subscription.user_id == User.id) - .options(selectinload(Subscription.user)) + .outerjoin(Tariff, Subscription.tariff_id == Tariff.id) + .options(selectinload(Subscription.user), selectinload(Subscription.tariff)) .where( and_( Subscription.status == SubscriptionStatus.ACTIVE.value, User.status == UserStatus.ACTIVE.value, Subscription.end_date <= threshold_date, Subscription.end_date > datetime.now(UTC), + # Не включаем активные суточные подписки — у них end_date всегда +24ч + ~and_( + Tariff.is_daily.is_(True), + Subscription.is_daily_paused.is_(False), + ), ) ) ) @@ -1048,7 +1056,7 @@ async def get_all_subscriptions(db: AsyncSession, page: int = 1, limit: int = 10 result = await db.execute( select(Subscription) - .options(selectinload(Subscription.user)) + .options(selectinload(Subscription.user), selectinload(Subscription.tariff)) .order_by(Subscription.created_at.desc()) .offset(offset) .limit(limit) @@ -1064,10 +1072,10 @@ async def get_subscriptions_batch( offset: int = 0, limit: int = 500, ) -> list[Subscription]: - """Получает подписки пачками для синхронизации. Загружает связанных пользователей.""" + """Получает подписки пачками для синхронизации. Загружает связанных пользователей и тарифы.""" result = await db.execute( select(Subscription) - .options(selectinload(Subscription.user)) + .options(selectinload(Subscription.user), selectinload(Subscription.tariff)) .order_by(Subscription.id) .offset(offset) .limit(limit) diff --git a/app/services/monitoring_service.py b/app/services/monitoring_service.py index 91b16607..9811f20b 100644 --- a/app/services/monitoring_service.py +++ b/app/services/monitoring_service.py @@ -330,10 +330,23 @@ class MonitoringService: is_active = subscription.status == SubscriptionStatus.ACTIVE.value and subscription.end_date > current_time if subscription.status == SubscriptionStatus.ACTIVE.value and subscription.end_date <= current_time: - subscription.status = SubscriptionStatus.EXPIRED.value - await db.commit() - is_active = False - logger.info("📝 Статус подписки обновлен на 'expired'", subscription_id=subscription.id) + # Суточные подписки управляются DailySubscriptionService — не экспайрим + tariff = getattr(subscription, 'tariff', None) + is_active_daily = ( + tariff is not None + and getattr(tariff, 'is_daily', False) + and not getattr(subscription, 'is_daily_paused', False) + ) + if is_active_daily: + logger.debug( + 'update_remnawave_user: пропуск expire для суточной подписки', + subscription_id=subscription.id, + ) + else: + subscription.status = SubscriptionStatus.EXPIRED.value + await db.commit() + is_active = False + logger.info("📝 Статус подписки обновлен на 'expired'", subscription_id=subscription.id) if not self.subscription_service.is_configured: logger.warning( diff --git a/app/services/remnawave_webhook_service.py b/app/services/remnawave_webhook_service.py index 1681736e..ff45297c 100644 --- a/app/services/remnawave_webhook_service.py +++ b/app/services/remnawave_webhook_service.py @@ -499,6 +499,23 @@ class RemnaWaveWebhookService: self, db: AsyncSession, user: User, subscription: Subscription | None, data: dict ) -> None: if subscription: + # Суточные подписки управляются DailySubscriptionService — не деактивируем + tariff = getattr(subscription, 'tariff', None) + is_active_daily = ( + tariff is not None + and getattr(tariff, 'is_daily', False) + and not getattr(subscription, 'is_daily_paused', False) + ) + if is_active_daily: + logger.info( + 'Webhook: пропуск disabled для суточной подписки', + subscription_id=subscription.id, + user_id=user.id, + ) + self._stamp_webhook_update(subscription) + await db.commit() + return + self._stamp_webhook_update(subscription) if subscription.status != SubscriptionStatus.DISABLED.value: await deactivate_subscription(db, subscription)