fix: false subscription expiry notifications — 4 bugs fixed

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
This commit is contained in:
Fringg
2026-04-29 05:47:56 +03:00
parent c743fc81a5
commit 134e7fb0e1
+40 -1
View File
@@ -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,
)
)
)