Fix text dialog routing and club card registration recovery
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-09-13 21:39:40 +09:00
parent 3c1a6a02a5
commit f3f8d0f737
28 changed files with 788 additions and 334 deletions

View File

@@ -98,109 +98,9 @@ def mask_account_number(account_number: str, show_last_digits: int = 4) -> str:
def parse_accounts_from_message(text: str) -> List[str]:
"""
Извлекает все валидные номера счетов из текста сообщения.
Поддерживает формат: "КАРТА СЧЕТ" (например "2521 11-22-33-44-55-66-77")
или просто "СЧЕТ" (например "11-22-33-44-55-66-77")
Также обрабатывает многострочный текст из кабинета:
Запись начинается со слова "Viposnova" и содержит несколько строк до следующего "Viposnova":
"Viposnova 16-11-2025 22:19:36
17-24-66-42-38-31-53
0.00 2918"
Args:
text: Текст сообщения
Returns:
List[str]: Список найденных строк (может включать номер карты и счета через пробел)
"""
if not text:
return []
accounts = []
# Группируем строки по записям (от "Viposnova" до следующего "Viposnova")
lines = text.strip().split('\n')
current_record = []
records = []
for line in lines:
stripped = line.strip()
# Если строка начинается с Viposnova и у нас уже есть текущая запись - сохраняем её
if stripped.startswith('Viposnova') and current_record:
records.append(' '.join(current_record))
current_record = [stripped]
else:
current_record.append(stripped)
# Добавляем последнюю запись
if current_record:
records.append(' '.join(current_record))
# Обрабатываем каждую запись
for record in records:
parts = record.split()
# Ищем счет в записи
account_number = None
account_idx = None
for i, part in enumerate(parts):
if re.match(r'^\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$', part):
account_number = format_account_number(part)
account_idx = i
break
if not account_number or account_number in accounts:
continue
# Ищем клубную карту (4-значное число после счета)
card = None
if account_idx is not None:
for j in range(account_idx + 1, len(parts)):
if re.match(r'^\d{4}$', parts[j]):
card = parts[j]
break
# Добавляем результат
if card:
full_account = f"{card} {account_number}"
if full_account not in accounts:
accounts.append(full_account)
else:
accounts.append(account_number)
# Если построчная обработка ничего не нашла, используем старый метод
if not accounts:
# Паттерн 1: номер карты (4 цифры) + пробел + счет (7 пар цифр)
pattern_with_card = r'(\d{4})\s+(\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2})'
# Находим все совпадения с картой и удаляем их из текста
text_copy = text
for match in re.finditer(pattern_with_card, text):
card = match.group(1)
account = match.group(2)
formatted = format_account_number(account)
if formatted:
full_account = f"{card} {formatted}"
if full_account not in accounts:
accounts.append(full_account)
# Удаляем это совпадение из копии текста, чтобы не найти повторно
text_copy = text_copy.replace(match.group(0), ' ' * len(match.group(0)))
# Паттерн 2: только счет (7 пар цифр) в оставшемся тексте
pattern_only_account = r'\b\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}\b'
matches_only = re.findall(pattern_only_account, text_copy)
for match in matches_only:
formatted = format_account_number(match)
if formatted and formatted not in accounts:
# Дополнительная проверка - этот счет не должен быть частью уже найденных "карта + счет"
is_duplicate = any(formatted in acc for acc in accounts)
if not is_duplicate:
accounts.append(formatted)
return accounts
"""Return all recognized records, preserving card numbers and leading zeroes."""
from .account_input import parse_account_records
return parse_account_records(text or "")[0]
def search_accounts_by_pattern(pattern: str, account_list: List[str]) -> List[str]: