diff --git a/app/database/crud/user.py b/app/database/crud/user.py index e9dea8c2..a5e60ae1 100644 --- a/app/database/crud/user.py +++ b/app/database/crud/user.py @@ -39,7 +39,6 @@ async def get_user_by_id(db: AsyncSession, user_id: int) -> Optional[User]: .options( selectinload(User.subscription), selectinload(User.promo_group), - selectinload(User.referrer), ) .where(User.id == user_id) ) @@ -57,7 +56,6 @@ async def get_user_by_telegram_id(db: AsyncSession, telegram_id: int) -> Optiona .options( selectinload(User.subscription), selectinload(User.promo_group), - selectinload(User.referrer), ) .where(User.telegram_id == telegram_id) ) diff --git a/app/services/admin_notification_service.py b/app/services/admin_notification_service.py index cd31b37c..1aa3efeb 100644 --- a/app/services/admin_notification_service.py +++ b/app/services/admin_notification_service.py @@ -3,6 +3,7 @@ from typing import Optional, Dict, Any, List from datetime import datetime from aiogram import Bot, types from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.config import settings @@ -344,22 +345,35 @@ class AdminNotificationService: async def send_balance_topup_notification( self, + db: AsyncSession, user: User, transaction: Transaction, - old_balance: int, - *, - topup_status: str, - referrer_info: str, - subscription: Subscription | None, - promo_group: PromoGroup | None, + old_balance: int ) -> bool: if not self._is_enabled(): return False try: + deposit_count_result = await db.execute( + select(func.count()) + .select_from(Transaction) + .where( + Transaction.user_id == user.id, + Transaction.type == TransactionType.DEPOSIT.value, + Transaction.is_completed.is_(True) + ) + ) + deposit_count = deposit_count_result.scalar_one() or 0 + topup_status = "🆕 Первое пополнение" if deposit_count <= 1 else "🔄 Пополнение" payment_method = self._get_payment_method_display(transaction.payment_method) balance_change = user.balance_kopeks - old_balance + referrer_info = await self._get_referrer_info(db, user.referred_by_id) + subscription_result = await db.execute( + select(Subscription).where(Subscription.user_id == user.id) + ) + subscription = subscription_result.scalar_one_or_none() subscription_status = self._get_subscription_status(subscription) + promo_group = await self._get_user_promo_group(db, user) promo_block = self._format_promo_group_block(promo_group) message = f"""💰 ПОПОЛНЕНИЕ БАЛАНСА diff --git a/app/services/payment_service.py b/app/services/payment_service.py index d9622019..81784cdf 100644 --- a/app/services/payment_service.py +++ b/app/services/payment_service.py @@ -24,7 +24,6 @@ from app.external.cryptobot import CryptoBotService from app.utils.currency_converter import currency_converter from app.database.database import get_db from app.localization.texts import get_texts -from app.utils.user_utils import format_referrer_info from app.services.subscription_checkout_service import ( has_subscription_checkout_draft, should_offer_checkout_resume, @@ -179,19 +178,10 @@ class PaymentService: user = await get_user_by_id(db, user_id) if user: old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - + user.balance_kopeks += amount_kopeks user.updated_at = datetime.utcnow() - - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - + await db.commit() await db.refresh(user) @@ -217,13 +207,7 @@ class PaymentService: from app.services.admin_notification_service import AdminNotificationService notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( - user, - transaction, - old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, + db, user, transaction, old_balance ) except Exception as e: logger.error(f"Ошибка отправки уведомления о пополнении Stars: {e}") @@ -491,19 +475,10 @@ class PaymentService: user = await get_user_by_id(db, updated_payment.user_id) if user: old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - + user.balance_kopeks += updated_payment.amount_kopeks user.updated_at = datetime.utcnow() - - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - + await db.commit() await db.refresh(user) @@ -518,13 +493,7 @@ class PaymentService: from app.services.admin_notification_service import AdminNotificationService notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( - user, - transaction, - old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, + db, user, transaction, old_balance ) except Exception as e: logger.error(f"Ошибка отправки уведомления о пополнении YooKassa: {e}") @@ -1106,19 +1075,9 @@ class PaymentService: return False old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - user.balance_kopeks += payment.amount_kopeks user.updated_at = datetime.utcnow() - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - await db.commit() await db.refresh(user) @@ -1148,13 +1107,10 @@ class PaymentService: notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( + db, user, transaction, old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, ) except Exception as notify_error: logger.error( @@ -1312,19 +1268,8 @@ class PaymentService: await link_pal24_payment_to_transaction(db, payment, transaction.id) old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - user.balance_kopeks += payment.amount_kopeks user.updated_at = datetime.utcnow() - - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - await db.commit() await db.refresh(user) @@ -1341,13 +1286,10 @@ class PaymentService: notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( + db, user, transaction, old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, ) except Exception as notify_error: logger.error("Ошибка отправки админ уведомления Pal24: %s", notify_error) @@ -1582,19 +1524,10 @@ class PaymentService: user = await get_user_by_id(db, updated_payment.user_id) if user: old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - + user.balance_kopeks += amount_kopeks user.updated_at = datetime.utcnow() - - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - + await db.commit() await db.refresh(user) @@ -1609,13 +1542,7 @@ class PaymentService: from app.services.admin_notification_service import AdminNotificationService notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( - user, - transaction, - old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, + db, user, transaction, old_balance ) except Exception as e: logger.error(f"Ошибка отправки уведомления о пополнении CryptoBot: {e}") diff --git a/app/services/tribute_service.py b/app/services/tribute_service.py index e9153e18..6d5de2eb 100644 --- a/app/services/tribute_service.py +++ b/app/services/tribute_service.py @@ -11,10 +11,9 @@ from app.database.models import Transaction, TransactionType, PaymentMethod from app.database.crud.transaction import ( create_transaction, get_transaction_by_external_id, complete_transaction ) -from app.database.crud.user import get_user_by_telegram_id +from app.database.crud.user import get_user_by_telegram_id, add_user_balance from app.external.tribute import TributeService as TributeAPI from app.services.payment_service import PaymentService -from app.utils.user_utils import format_referrer_info logger = logging.getLogger(__name__) @@ -121,27 +120,14 @@ class TributeService: amount_kopeks=amount_kopeks, description=f"Пополнение через Tribute: {amount_kopeks/100}₽ (ID: {payment_id})" ) - + old_balance = user.balance_kopeks - was_first_topup = not user.has_made_first_topup - user.balance_kopeks += amount_kopeks user.updated_at = datetime.utcnow() - - if was_first_topup: - user.has_made_first_topup = True - - promo_group = getattr(user, "promo_group", None) - subscription = getattr(user, "subscription", None) - referrer_info = format_referrer_info(user) - topup_status = "🆕 Первое пополнение" if was_first_topup else "🔄 Пополнение" - + await session.commit() - await session.refresh(user) - - logger.info( - f"✅ Баланс пользователя {user_telegram_id} обновлен: {old_balance} -> {user.balance_kopeks} коп (+{amount_kopeks})" - ) + + logger.info(f"✅ Баланс пользователя {user_telegram_id} обновлен: {old_balance} -> {user.balance_kopeks} коп (+{amount_kopeks})") logger.info(f"✅ Создана транзакция ID: {transaction.id}") try: @@ -150,7 +136,8 @@ class TributeService: except Exception as e: logger.error(f"Ошибка обработки реферального пополнения Tribute: {e}") - if was_first_topup: + if not user.has_made_first_topup: + user.has_made_first_topup = True logger.info(f"Отмечен первый топап для пользователя {user_telegram_id}") @@ -158,13 +145,7 @@ class TributeService: from app.services.admin_notification_service import AdminNotificationService notification_service = AdminNotificationService(self.bot) await notification_service.send_balance_topup_notification( - user, - transaction, - old_balance, - topup_status=topup_status, - referrer_info=referrer_info, - subscription=subscription, - promo_group=promo_group, + session, user, transaction, old_balance ) except Exception as e: logger.error(f"Ошибка отправки уведомления о Tribute пополнении: {e}") diff --git a/app/utils/user_utils.py b/app/utils/user_utils.py index 06b08db4..e2a73c49 100644 --- a/app/utils/user_utils.py +++ b/app/utils/user_utils.py @@ -12,25 +12,6 @@ from app.database.models import User, ReferralEarning, Transaction, TransactionT logger = logging.getLogger(__name__) -def format_referrer_info(user: User) -> str: - """Return formatted referrer info for admin notifications.""" - - referred_by_id = getattr(user, "referred_by_id", None) - - 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}" - - async def generate_unique_referral_code(db: AsyncSession, telegram_id: int) -> str: max_attempts = 10