fix: обработка формата 'КАРТА СЧЕТ' в AccountParticipationService

Проблема:
- Когда админ отправляет счет в чат и нажимает 'Добавить в розыгрыш'
- Используется другой обработчик (account_handlers.py)
- Он вызывает add_account_to_lottery() которая НЕ разбирала формат

Решение:
- Добавлен split() по пробелу в add_account_to_lottery()
- Добавлено получение Account и user через AccountService
- Теперь сохраняются user_id и account_id
- Улучшены сообщения с указанием номера карты

Теперь ОБА пути работают:
1. Массовое добавление через админ-панель
2. Добавление из детектированных счетов в чате
This commit is contained in:
2025-11-17 09:09:24 +09:00
parent 1d715d4f63
commit 29a6ac2bd2
3 changed files with 54 additions and 10 deletions

View File

@@ -1 +1 @@
859161 866736

View File

@@ -539,6 +539,9 @@ class ParticipationService:
@staticmethod @staticmethod
async def add_participants_by_accounts_bulk(session: AsyncSession, lottery_id: int, account_numbers: List[str]) -> Dict[str, Any]: async def add_participants_by_accounts_bulk(session: AsyncSession, lottery_id: int, account_numbers: List[str]) -> Dict[str, Any]:
"""Массовое добавление участников по номерам счетов""" """Массовое добавление участников по номерам счетов"""
import logging
logger = logging.getLogger(__name__)
results = { results = {
"added": 0, "added": 0,
"skipped": 0, "skipped": 0,
@@ -552,27 +555,38 @@ class ParticipationService:
if not account_input: if not account_input:
continue continue
logger.info(f"DEBUG: Processing account_input={account_input!r}")
try: try:
# Разделяем по пробелу: левая часть - номер карты, правая - номер счета # Разделяем по пробелу: левая часть - номер карты, правая - номер счета
parts = account_input.split() parts = account_input.split()
logger.info(f"DEBUG: After split: parts={parts}, len={len(parts)}")
if len(parts) == 2: if len(parts) == 2:
card_number = parts[0] # Номер клубной карты card_number = parts[0] # Номер клубной карты
account_number = parts[1] # Номер счета account_number = parts[1] # Номер счета
logger.info(f"DEBUG: 2 parts - card={card_number!r}, account={account_number!r}")
elif len(parts) == 1: elif len(parts) == 1:
# Если нет пробела, считаем что это просто номер счета # Если нет пробела, считаем что это просто номер счета
card_number = None card_number = None
account_number = parts[0] account_number = parts[0]
logger.info(f"DEBUG: 1 part - account={account_number!r}")
else: else:
logger.info(f"DEBUG: Invalid parts count={len(parts)}")
results["invalid_accounts"].append(account_input) results["invalid_accounts"].append(account_input)
results["errors"].append(f"Неверный формат: {account_input}") results["errors"].append(f"Неверный формат: {account_input}")
continue continue
# Валидируем и форматируем номер счета # Валидируем и форматируем номер счета
logger.info(f"DEBUG: Before format_account_number: {account_number!r}")
formatted_account = format_account_number(account_number) formatted_account = format_account_number(account_number)
logger.info(f"DEBUG: After format_account_number: {formatted_account!r}")
if not formatted_account: if not formatted_account:
card_info = f" (карта: {card_number})" if card_number else "" card_info = f" (карта: {card_number})" if card_number else ""
results["invalid_accounts"].append(account_input) results["invalid_accounts"].append(account_input)
results["errors"].append(f"Неверный формат счета: {account_number}{card_info}") results["errors"].append(f"Неверный формат счета: {account_number}{card_info}")
logger.error(f"DEBUG: Format failed for {account_number!r}")
continue continue
# Ищем владельца счёта через таблицу Account # Ищем владельца счёта через таблицу Account

View File

@@ -18,17 +18,34 @@ class AccountParticipationService:
account_number: str account_number: str
) -> Dict[str, Any]: ) -> Dict[str, Any]:
""" """
Добавить счет в розыгрыш Добавить счет в розыгрыш.
Поддерживает форматы: "КАРТА СЧЕТ" или просто "СЧЕТ"
Returns: Returns:
Dict с ключами: success, message, account_number Dict с ключами: success, message, account_number
""" """
# Валидируем и форматируем # Разделяем по пробелу если есть номер карты
formatted_account = format_account_number(account_number) parts = account_number.split()
if not formatted_account: if len(parts) == 2:
card_number = parts[0]
account_to_format = parts[1]
elif len(parts) == 1:
card_number = None
account_to_format = parts[0]
else:
return { return {
"success": False, "success": False,
"message": f"Неверный формат счета: {account_number}", "message": f"Неверный формат: {account_number}",
"account_number": account_number
}
# Валидируем и форматируем только часть счета
formatted_account = format_account_number(account_to_format)
if not formatted_account:
card_info = f" (карта: {card_number})" if card_number else ""
return {
"success": False,
"message": f"Неверный формат счета: {account_to_format}{card_info}",
"account_number": account_number "account_number": account_number
} }
@@ -49,24 +66,37 @@ class AccountParticipationService:
) )
) )
if existing.scalar_one_or_none(): if existing.scalar_one_or_none():
card_info = f" (карта: {card_number})" if card_number else ""
return { return {
"success": False, "success": False,
"message": f"Счет {formatted_account} уже участвует в розыгрыше", "message": f"Счет {formatted_account}{card_info} уже участвует в розыгрыше",
"account_number": formatted_account "account_number": formatted_account
} }
# Добавляем участие # Получаем запись Account и владельца
from ..core.registration_services import AccountService
from ..core.models import Account
user = await AccountService.get_account_owner(session, formatted_account)
account_record = await session.execute(
select(Account).where(Account.account_number == formatted_account)
)
account_record = account_record.scalar_one_or_none()
# Добавляем участие с полными данными
participation = Participation( participation = Participation(
lottery_id=lottery_id, lottery_id=lottery_id,
account_number=formatted_account, account_number=formatted_account,
user_id=None # Без привязки к пользователю user_id=user.id if user else None,
account_id=account_record.id if account_record else None
) )
session.add(participation) session.add(participation)
await session.commit() await session.commit()
card_info = f" (карта: {card_number})" if card_number else ""
return { return {
"success": True, "success": True,
"message": f"Счет {formatted_account} добавлен в розыгрыш", "message": f"Счет {formatted_account}{card_info} добавлен в розыгрыш",
"account_number": formatted_account "account_number": formatted_account
} }