From 134e7fb0e1999f6404e2d06f38aebdb6af550ec1 Mon Sep 17 00:00:00 2001 From: Fringg Date: Wed, 29 Apr 2026 05:47:56 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20false=20subscription=20expiry=20notifica?= =?UTF-8?q?tions=20=E2=80=94=204=20bugs=20fixed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. _check_expired_subscription_followups: added Subscription.status=EXPIRED filter (was matching ALL statuses including ACTIVE), User.status=ACTIVE filter, and 30-day lookback window to stop scanning ancient subscriptions 2. _get_expiring_paid_subscriptions: added User.status=ACTIVE filter to prevent sending "expiring" notifications to blocked/deleted users 3. Multi-tariff: before sending expired/followup notifications, check if user has another ACTIVE subscription with end_date > now — skip if they still have service through another tariff 4. Multi-tariff: same check for _check_expired_subscriptions — don't send "subscription expired" if user has another active sub --- app/services/monitoring_service.py | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/app/services/monitoring_service.py b/app/services/monitoring_service.py index 4264902f..a3476e01 100644 --- a/app/services/monitoring_service.py +++ b/app/services/monitoring_service.py @@ -373,7 +373,22 @@ class MonitoringService: user = await get_user_by_id(db, subscription.user_id) if user and self.bot: - await self._send_subscription_expired_notification(user, subscription, tariff_name=_tariff_name) + # Skip notification if user has another ACTIVE subscription (multi-tariff) + skip_notify = False + if settings.is_multi_tariff_enabled(): + other_active = await db.execute( + select(Subscription.id) + .where( + Subscription.user_id == user.id, + Subscription.id != subscription.id, + Subscription.status == SubscriptionStatus.ACTIVE.value, + Subscription.end_date > datetime.now(UTC), + ) + .limit(1) + ) + skip_notify = other_active.scalar_one_or_none() is not None + if not skip_notify: + await self._send_subscription_expired_notification(user, subscription, tariff_name=_tariff_name) logger.info( "🔴 Подписка пользователя истекла и статус изменен на 'expired'", user_id=subscription.user_id @@ -965,8 +980,12 @@ class MonitoringService: try: now = datetime.now(UTC) + # Lookback window — don't re-check subscriptions expired more than 30 days ago + lookback = now - timedelta(days=30) + result = await db.execute( select(Subscription) + .join(User, Subscription.user_id == User.id) .options( selectinload(Subscription.user), selectinload(Subscription.tariff), @@ -974,7 +993,10 @@ class MonitoringService: .where( and_( Subscription.is_trial == False, + Subscription.status == SubscriptionStatus.EXPIRED.value, Subscription.end_date <= now, + Subscription.end_date >= lookback, + User.status == UserStatus.ACTIVE.value, ) ) ) @@ -998,6 +1020,21 @@ class MonitoringService: if subscription.end_date is None: continue + # Skip if user has another ACTIVE subscription — they still have service + if settings.is_multi_tariff_enabled(): + other_active = await db.execute( + select(Subscription.id) + .where( + Subscription.user_id == user.id, + Subscription.id != subscription.id, + Subscription.status == SubscriptionStatus.ACTIVE.value, + Subscription.end_date > now, + ) + .limit(1) + ) + if other_active.scalar_one_or_none() is not None: + continue + time_since_end = now - subscription.end_date if time_since_end.total_seconds() < 0: continue @@ -1090,6 +1127,7 @@ class MonitoringService: result = await db.execute( select(Subscription) + .join(User, Subscription.user_id == User.id) .options( selectinload(Subscription.user), selectinload(Subscription.tariff), @@ -1100,6 +1138,7 @@ class MonitoringService: Subscription.is_trial == False, Subscription.end_date > current_time, Subscription.end_date <= threshold_date, + User.status == UserStatus.ACTIVE.value, ) ) )