fix: inactive user cleanup deletes users with paid subscriptions

The get_inactive_users query filtered only by last_activity (last bot
interaction), ignoring subscription end dates. Users who bought long
subscriptions (3-6-12 months) but didn't interact with the bot got
flagged as inactive and deleted+banned while their subscription was
still active or recently expired.

Fix: add SQL subquery excluding users who have ANY subscription with
end_date >= threshold_date. A user is now only deletable when BOTH
their last_activity AND their latest subscription end_date are older
than the configured inactivity period.
This commit is contained in:
Fringg
2026-04-23 03:40:45 +03:00
parent 29ae7089aa
commit 7005052156
+13 -1
View File
@@ -1112,6 +1112,12 @@ async def get_users_for_promo_segment(db: AsyncSession, segment: str) -> list[Us
async def get_inactive_users(db: AsyncSession, months: int = 3) -> list[User]:
threshold_date = datetime.now(UTC) - timedelta(days=months * 30)
# Подзапрос: пользователи, у которых есть подписка с end_date >= threshold
# (активная или недавно истёкшая) — таких удалять нельзя
users_with_recent_subs = (
select(Subscription.user_id).where(Subscription.end_date >= threshold_date).distinct().scalar_subquery()
)
result = await db.execute(
select(User)
.options(
@@ -1120,7 +1126,13 @@ async def get_inactive_users(db: AsyncSession, months: int = 3) -> list[User]:
selectinload(User.referrer),
selectinload(User.promo_group),
)
.where(and_(User.last_activity < threshold_date, User.status == UserStatus.ACTIVE.value))
.where(
and_(
User.last_activity < threshold_date,
User.status == UserStatus.ACTIVE.value,
User.id.not_in(users_with_recent_subs),
)
)
)
users = result.scalars().all()