""" Утилиты для работы с клиентскими счетами """ import re from typing import Optional, List def validate_account_number(account_number: str) -> bool: """ Проверяет корректность формата номера клиентского счета Формат: XX-XX-XX-XX-XX-XX-XX (7 пар цифр через дефис) Args: account_number: Номер счета для проверки Returns: bool: True если формат корректен, False иначе """ if not account_number: return False # Паттерн для 7 пар цифр через дефис pattern = r'^\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$' return bool(re.match(pattern, account_number)) def format_account_number(account_number: str) -> Optional[str]: """ Форматирует номер счета, убирая лишние символы Args: account_number: Исходный номер счета Returns: str: Отформатированный номер счета или None если некорректный """ if not account_number: return None # Убираем все символы кроме цифр digits_only = re.sub(r'\D', '', account_number) # Проверяем что осталось ровно 14 цифр if len(digits_only) != 14: return None # Форматируем как XX-XX-XX-XX-XX-XX-XX formatted = '-'.join([digits_only[i:i+2] for i in range(0, 14, 2)]) return formatted def generate_account_number() -> str: """ Генерирует случайный номер клиентского счета для тестирования Returns: str: Сгенерированный номер счета """ import random # Генерируем 14 случайных цифр digits = ''.join([str(random.randint(0, 9)) for _ in range(14)]) # Форматируем return '-'.join([digits[i:i+2] for i in range(0, 14, 2)]) def mask_account_number(account_number: str, show_last_digits: int = 4) -> str: """ Маскирует номер счета для безопасного отображения Args: account_number: Полный номер счета show_last_digits: Количество последних цифр для отображения Returns: str: Замаскированный номер счета """ if not validate_account_number(account_number): return "Некорректный номер" if show_last_digits <= 0: return "**-**-**-**-**-**-**" # Убираем дефисы для работы с цифрами digits = account_number.replace('-', '') # Определяем сколько цифр показать show_digits = min(show_last_digits, len(digits)) # Создаем маску masked_digits = '*' * (len(digits) - show_digits) + digits[-show_digits:] # Возвращаем отформатированный результат (7 пар) return '-'.join([masked_digits[i:i+2] for i in range(0, 14, 2)]) def parse_accounts_from_message(text: str) -> List[str]: """ Извлекает все валидные номера счетов из текста сообщения Args: text: Текст сообщения Returns: List[str]: Список найденных и отформатированных номеров счетов """ if not text: return [] accounts = [] # Ищем паттерны счетов в тексте (7 пар цифр) pattern = r'\b\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}\b' matches = re.findall(pattern, text) for match in matches: formatted = format_account_number(match) if formatted and formatted not in accounts: accounts.append(formatted) return accounts def search_accounts_by_pattern(pattern: str, account_list: List[str]) -> List[str]: """ Ищет счета по частичному совпадению (1-2 пары цифр) Args: pattern: Паттерн для поиска (например "11-22" или "11") account_list: Список счетов для поиска Returns: List[str]: Список найденных счетов """ if not pattern or not account_list: return [] # Убираем лишние символы из паттерна clean_pattern = re.sub(r'[^\d-]', '', pattern).strip('-') if not clean_pattern: return [] results = [] for account in account_list: if clean_pattern in account: results.append(account) return results