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: