diff --git a/database/hot_leads.py b/database/hot_leads.py index 0a14c612..1b5c0bc6 100644 --- a/database/hot_leads.py +++ b/database/hot_leads.py @@ -18,6 +18,8 @@ async def get_hot_leads(session: AsyncSession): select(Payment.tg_id) .distinct() .where(Payment.amount > 0) + .where(Payment.status == "success") + .where(Payment.payment_system.notin_(["referral", "coupon", "cashback"])) .where(~Payment.tg_id.in_(subquery)) ) diff --git a/database/statistics.py b/database/statistics.py index dfa1f561..f58aa429 100644 --- a/database/statistics.py +++ b/database/statistics.py @@ -160,7 +160,9 @@ async def count_hot_leads(session: AsyncSession) -> int: stmt = ( select(Payment.tg_id) + .where(Payment.amount > 0) .where(Payment.status == "success") + .where(Payment.payment_system.notin_(["referral", "coupon", "cashback"])) .where(not_(exists(subquery_active_keys.where(Key.tg_id == Payment.tg_id)))) .distinct() ) diff --git a/handlers/admin/users/users_handler.py b/handlers/admin/users/users_handler.py index 3aac019f..f21941c2 100644 --- a/handlers/admin/users/users_handler.py +++ b/handlers/admin/users/users_handler.py @@ -965,6 +965,33 @@ async def confirm_admin_key_reissue( servers = await get_servers(session) cluster_servers = servers.get(cluster_id, []) + tariffs = await get_tariffs_for_cluster(session, cluster_id) + if not tariffs: + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton( + text="🔗 Привязать тариф", + callback_data=AdminPanelCallback(action="clusters").pack() + ) + ) + builder.row( + InlineKeyboardButton( + text="🔙 Назад", + callback_data=AdminUserEditorCallback( + action="users_key_edit", tg_id=tg_id, data=email + ).pack() + ) + ) + await callback_query.message.edit_text( + f"🚫 Невозможно пересоздать подписку\n\n" + f"📊 Информация о кластере:\n
" + f"🌐 Кластер: {cluster_id}\n" + f"⚠️ Статус: Нет привязанного тарифа\n
" + f"💡 Привяжите тариф к кластеру", + reply_markup=builder.as_markup() + ) + return + if USE_COUNTRY_SELECTION: unique_countries = {srv["server_name"] for srv in cluster_servers} await state.update_data(tg_id=tg_id, email=email, cluster_id=cluster_id) @@ -1005,11 +1032,42 @@ async def confirm_admin_key_reissue( @router.callback_query(F.data.startswith("admin_reissue_country|"), IsAdminFilter()) -async def admin_reissue_country(callback_query: CallbackQuery, session: AsyncSession): +async def admin_reissue_country(callback_query: CallbackQuery, session: AsyncSession, state: FSMContext): _, tg_id, email, country = callback_query.data.split("|") tg_id = int(tg_id) try: + data = await state.get_data() + cluster_id = data.get("cluster_id") + + if cluster_id: + tariffs = await get_tariffs_for_cluster(session, cluster_id) + if not tariffs: + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton( + text="🔗 Привязать тариф", + callback_data=AdminPanelCallback(action="clusters").pack() + ) + ) + builder.row( + InlineKeyboardButton( + text="🔙 Назад", + callback_data=AdminUserEditorCallback( + action="users_key_edit", tg_id=tg_id, data=email + ).pack() + ) + ) + await callback_query.message.edit_text( + f"🚫 Невозможно пересоздать подписку\n\n" + f"📊 Информация о кластере:\n
" + f"🌐 Кластер: {cluster_id}\n" + f"⚠️ Статус: Нет привязанного тарифа\n
" + f"💡 Привяжите тариф к кластеру", + reply_markup=builder.as_markup() + ) + return + result = await session.execute( select(Key.remnawave_link, Key.tariff_id).where(Key.email == email) ) diff --git a/handlers/keys/key_mode/key_create.py b/handlers/keys/key_mode/key_create.py index 40cd9046..c39fe424 100644 --- a/handlers/keys/key_mode/key_create.py +++ b/handlers/keys/key_mode/key_create.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta from typing import Any from collections import defaultdict from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select import pytz from aiogram import F, Router @@ -26,7 +27,9 @@ from database import ( get_tariffs_for_cluster, get_trial, ) +from database.models import Admin from database.tariffs import create_subgroup_hash, find_subgroup_by_hash +from handlers.admin.panel.keyboard import AdminPanelCallback from handlers.buttons import MAIN_MENU, PAYMENT from handlers.payments.robokassa_pay import handle_custom_amount_input from handlers.payments.stars_pay import process_custom_amount_input_stars @@ -103,14 +106,39 @@ async def handle_key_creation( tariffs = await get_tariffs_for_cluster(session, cluster_name) if not tariffs: + result = await session.execute(select(Admin).where(Admin.tg_id == tg_id)) + is_admin = result.scalar_one_or_none() is not None + + if is_admin: + builder = InlineKeyboardBuilder() + builder.row( + InlineKeyboardButton( + text="🔗 Привязать тариф", + callback_data=AdminPanelCallback(action="clusters").pack() + ) + ) + builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile")) + + text = ( + f"🚫 Невозможно создать подписку\n\n" + f"📊 Информация о кластере:\n
" + f"🌐 Кластер: {cluster_name}\n" + f"⚠️ Статус: Нет привязанного тарифа\n
" + f"💡 Привяжите тариф к кластеру" + ) + else: + builder = InlineKeyboardBuilder() + builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile")) + text = "❌ Нет доступных тарифов для выбора." + await edit_or_send_message( target_message=( message_or_query.message if isinstance(message_or_query, CallbackQuery) else message_or_query ), - text="❌ Нет доступных тарифов для выбора.", - reply_markup=None, + text=text, + reply_markup=builder.as_markup(), ) return