Improved hot lead logic

This commit is contained in:
Capybara-z
2025-08-29 00:06:47 +03:00
parent a54310da27
commit 41b7423dc9
10 changed files with 305 additions and 74 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ async def get_hot_leads(session: AsyncSession):
"""
Возвращает пользователей, у которых есть успешные оплаты, но нет активных ключей.
"""
subquery = select(Key.tg_id).distinct()
subquery = select(Key.tg_id).where(Key.expiry_time > func.extract("epoch", func.now()) * 1000).distinct()
stmt = (
select(Payment.tg_id)
@@ -20,4 +20,4 @@ async def get_hot_leads(session: AsyncSession):
)
result = await session.execute(stmt)
return [row.tg_id for row in result]
return [row.tg_id for row in result]
+7
View File
@@ -5,6 +5,7 @@ from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from database.models import Key, User
from database.notifications import clear_hot_lead_notifications
from logger import logger
@@ -41,6 +42,12 @@ async def store_key(
session.add(new_key)
await session.commit()
logger.info(f"✅ Ключ сохранён: tg_id={tg_id}, client_id={client_id}, server_id={server_id}")
try:
await clear_hot_lead_notifications(session, tg_id)
except Exception as e:
pass
except SQLAlchemyError as e:
logger.error(f"❌ Ошибка при сохранении ключа: {e}")
await session.rollback()
+52
View File
@@ -5,6 +5,7 @@ from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from config import DISCOUNT_ACTIVE_HOURS
from database.models import Key, Notification, User
from logger import logger
@@ -64,6 +65,57 @@ async def get_last_notification_time(session: AsyncSession, tg_id: int, notifica
return None
async def check_hot_lead_discount(session: AsyncSession, tg_id: int) -> dict:
try:
result = await session.execute(
select(Notification.notification_type, Notification.last_notification_time)
.where(Notification.tg_id == tg_id)
.where(Notification.notification_type.in_(['hot_lead_step_2', 'hot_lead_step_3']))
.order_by(Notification.last_notification_time.desc())
.limit(1)
)
row = result.first()
if not row:
return {"available": False}
notification_type, last_time = row
expires_at = last_time + timedelta(hours=DISCOUNT_ACTIVE_HOURS)
current_time = datetime.utcnow()
if current_time > expires_at:
return {"available": False}
tariff_group = "discounts" if notification_type == "hot_lead_step_2" else "discounts_max"
return {
"available": True,
"type": notification_type,
"tariff_group": tariff_group,
"expires_at": expires_at
}
except Exception as e:
logger.error(f"❌ Ошибка при проверке скидки горячего лида для {tg_id}: {e}")
return {"available": False}
async def clear_hot_lead_notifications(session: AsyncSession, tg_id: int):
try:
await session.execute(
delete(Notification).where(
Notification.tg_id == tg_id,
Notification.notification_type.in_(['hot_lead_step_1', 'hot_lead_step_2', 'hot_lead_step_3', 'hot_lead_step_2_expired'])
)
)
await session.commit()
logger.info(f"✅ Уведомления о скидках горячих лидов очищены для пользователя {tg_id}")
except SQLAlchemyError as e:
logger.error(f"❌ Ошибка при очистке уведомлений о скидках для {tg_id}: {e}")
await session.rollback()
async def check_notifications_bulk(
session: AsyncSession,
notification_type: str,