diff --git a/README.md b/README.md
index 77eb9951..f1ad88dd 100644
--- a/README.md
+++ b/README.md
@@ -785,7 +785,7 @@ LOG_FILE=logs/bot.log
- 📊 **Расширенная фильтрация** пользователей (баланс, траты, активность)
👥 **Управление пользователями**
-- 🔍 Поиск, фильтры и детальные карточки
+- 🔍 Поиск по ID, имени, юзернейму, Telegram ID и фильтры
- 💰 Ручное изменение баланса
- 📱 Изменение лимитов устройств, трафика, серверов
- 🔄 Сброс HWID и перегенерация подписки
diff --git a/app/database/crud/user.py b/app/database/crud/user.py
index 67112086..8613ad20 100644
--- a/app/database/crud/user.py
+++ b/app/database/crud/user.py
@@ -515,6 +515,7 @@ async def get_users_list(
if search.isdigit():
conditions.append(User.telegram_id == int(search))
+ conditions.append(User.id == int(search)) # Add support for searching by internal user ID
query = query.where(or_(*conditions))
@@ -612,6 +613,7 @@ async def get_users_count(
if search.isdigit():
conditions.append(User.telegram_id == int(search))
+ conditions.append(User.id == int(search)) # Add support for searching by internal user ID
query = query.where(or_(*conditions))
diff --git a/app/services/admin_notification_service.py b/app/services/admin_notification_service.py
index ab95c1ba..5da6c2cb 100644
--- a/app/services/admin_notification_service.py
+++ b/app/services/admin_notification_service.py
@@ -196,9 +196,9 @@ class AdminNotificationService:
message = f"""🎯 АКТИВАЦИЯ ТРИАЛА
-👤 Пользователь: {user.full_name}
+👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}
🆔 Telegram ID: {user.telegram_id}
-📱 Username: @{user.username or 'отсутствует'}
+📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}
👥 Статус: {user_status}
{promo_block}
@@ -254,9 +254,9 @@ class AdminNotificationService:
message = f"""💎 {event_type}
-👤 Пользователь: {user.full_name}
+👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}
🆔 Telegram ID: {user.telegram_id}
-📱 Username: @{user.username or 'отсутствует'}
+📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}
👥 Статус: {user_status}
{promo_block}
@@ -375,9 +375,9 @@ class AdminNotificationService:
return f"""💰 ПОПОЛНЕНИЕ БАЛАНСА
-👤 Пользователь: {user.full_name}
+👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}
🆔 Telegram ID: {user.telegram_id}
-📱 Username: @{user.username or 'отсутствует'}
+📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}
💳 Статус: {topup_status}
{promo_block}
@@ -554,9 +554,9 @@ class AdminNotificationService:
message = f"""⏰ ПРОДЛЕНИЕ ПОДПИСКИ
-👤 Пользователь: {user.full_name}
+👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}
🆔 Telegram ID: {user.telegram_id}
-📱 Username: @{user.username or 'отсутствует'}
+📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}
{promo_block}
@@ -604,9 +604,9 @@ class AdminNotificationService:
message_lines = [
"🎫 АКТИВАЦИЯ ПРОМОКОДА",
"",
- f"👤 Пользователь: {user.full_name}",
+ f"👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}",
f"🆔 Telegram ID: {user.telegram_id}",
- f"📱 Username: @{user.username or 'отсутствует'}",
+ f"📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}",
"",
promo_block,
"",
@@ -731,9 +731,9 @@ class AdminNotificationService:
message_lines = [
f"{title}",
"",
- f"👤 Пользователь: {user.full_name}",
+ f"👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}",
f"🆔 Telegram ID: {user.telegram_id}",
- f"📱 Username: @{user.username or 'отсутствует'}",
+ f"📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}",
"",
self._format_promo_group_block(new_group, title="Новая промогруппа", icon="🏆"),
]
@@ -1115,9 +1115,9 @@ class AdminNotificationService:
message_lines = [
f"{title}",
"",
- f"👤 Пользователь: {user.full_name}",
+ f"👤 Пользователь: {getattr(user, 'first_name', '') or getattr(user, 'username', '') or f"ID{getattr(user, 'telegram_id', 'Unknown')}"}",
f"🆔 Telegram ID: {user.telegram_id}",
- f"📱 Username: @{user.username or 'отсутствует'}",
+ f"📱 Username: @{getattr(user, 'username', None) or 'отсутствует'}",
"",
promo_block,
"",
diff --git a/app/services/payment/yookassa.py b/app/services/payment/yookassa.py
index ca3d0574..778d35c2 100644
--- a/app/services/payment/yookassa.py
+++ b/app/services/payment/yookassa.py
@@ -405,7 +405,10 @@ class YooKassaPaymentMixin:
# Используем обновленные данные или исходные, если не удалось обновить
subscription = full_user.subscription if full_user else getattr(user, "subscription", None)
promo_group = full_user.promo_group if full_user else getattr(user, "promo_group", None)
- referrer_info = format_referrer_info(full_user if full_user else user)
+
+ # Используем full_user для форматирования реферальной информации, чтобы избежать проблем с ленивой загрузкой
+ user_for_referrer = full_user if full_user else user
+ referrer_info = format_referrer_info(user_for_referrer)
topup_status = (
"🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение"
)
diff --git a/app/utils/user_utils.py b/app/utils/user_utils.py
index 06b08db4..95f37de2 100644
--- a/app/utils/user_utils.py
+++ b/app/utils/user_utils.py
@@ -20,15 +20,26 @@ def format_referrer_info(user: User) -> str:
if not referred_by_id:
return "Нет"
- referrer = getattr(user, "referrer", None)
-
- if not referrer:
- return f"ID {referred_by_id} (не найден)"
-
- if referrer.username:
- return f"@{referrer.username} (ID: {referred_by_id})"
-
- return f"ID {referrer.telegram_id}"
+ try:
+ # Проверяем, является ли referrer обычным объектом или InstrumentedList
+ referrer = getattr(user, "referrer", None)
+
+ # Если referrer это InstrumentedList или None, то возвращаем информацию по ID
+ if referrer is None:
+ return f"ID {referred_by_id} (не найден)"
+
+ # Пытаемся получить атрибуты referrer, если они доступны
+ referrer_username = getattr(referrer, "username", None)
+ referrer_telegram_id = getattr(referrer, "telegram_id", None)
+
+ if referrer_username:
+ return f"@{referrer_username} (ID: {referred_by_id})"
+
+ return f"ID {referrer_telegram_id or referred_by_id}"
+
+ except (AttributeError, TypeError):
+ # Если возникла ошибка при обращении к атрибутам, просто возвращаем ID
+ return f"ID {referred_by_id} (ошибка загрузки)"
async def generate_unique_referral_code(db: AsyncSession, telegram_id: int) -> str: