fix: parse account number format with club card
- Changed logic to split input by space: left = club card number, right = account number - Updated add_participants_by_accounts_bulk() to handle '2521 12-64-89-29-62-40-74' format - Updated remove_participants_by_accounts_bulk() with same logic - Now shows club card number in details: 'Name (card: 2521, account: 12-64-89-29-62-40-74)' - Backwards compatible: still works with just account number (no space)
This commit is contained in:
126
CODE_CLEANUP_REPORT.md
Normal file
126
CODE_CLEANUP_REPORT.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# Результаты очистки кода
|
||||||
|
|
||||||
|
## Дата: 17 ноября 2025 г.
|
||||||
|
|
||||||
|
### Выполненные действия:
|
||||||
|
|
||||||
|
## 1. Удалены дублирующиеся обработчики из main.py
|
||||||
|
|
||||||
|
**Удалено:**
|
||||||
|
- `test_callback_handler` - тестовый callback (не используется в продакшене)
|
||||||
|
- `admin_panel_handler` - дублируется с admin_panel.py
|
||||||
|
- `lottery_management_handler` - дублируется с admin_panel.py
|
||||||
|
- `conduct_lottery_admin_handler` - дублируется с admin_panel.py
|
||||||
|
- `conduct_specific_lottery_handler` - дублируется с admin_panel.py
|
||||||
|
|
||||||
|
**Оставлено:**
|
||||||
|
- `cmd_start` - обработчик команды /start
|
||||||
|
- `cmd_admin` - упрощен, теперь напрямую показывает админ панель
|
||||||
|
- `active_lotteries_handler` - показ активных розыгрышей
|
||||||
|
- `back_to_main_handler` - возврат в главное меню
|
||||||
|
|
||||||
|
## 2. Очищены методы BotController
|
||||||
|
|
||||||
|
**Удалено из `src/controllers/bot_controller.py`:**
|
||||||
|
- `handle_admin_panel()` - перенесено в admin_panel.py
|
||||||
|
- `handle_lottery_management()` - перенесено в admin_panel.py
|
||||||
|
- `handle_conduct_lottery_admin()` - перенесено в admin_panel.py
|
||||||
|
- `handle_conduct_lottery()` - перенесено в admin_panel.py
|
||||||
|
|
||||||
|
**Оставлено:**
|
||||||
|
- `handle_start()` - обработка команды /start
|
||||||
|
- `handle_active_lotteries()` - показ активных розыгрышей
|
||||||
|
- `is_admin()` - проверка прав администратора
|
||||||
|
|
||||||
|
## 3. Упрощены клавиатуры в ui.py
|
||||||
|
|
||||||
|
**Удалено из `src/components/ui.py`:**
|
||||||
|
- `get_lottery_management_keyboard()` - используется локальная версия в admin_panel.py
|
||||||
|
- `get_lottery_keyboard()` - не используется
|
||||||
|
- `get_conduct_lottery_keyboard()` - не используется
|
||||||
|
|
||||||
|
**Оставлено:**
|
||||||
|
- `get_main_keyboard()` - главная клавиатура бота
|
||||||
|
- `get_admin_keyboard()` - админская панель
|
||||||
|
|
||||||
|
## 4. Упрощены интерфейсы
|
||||||
|
|
||||||
|
**IBotController (`src/interfaces/base.py`):**
|
||||||
|
- Было: 6 методов
|
||||||
|
- Стало: 2 метода
|
||||||
|
- `handle_start()`
|
||||||
|
- `handle_active_lotteries()`
|
||||||
|
|
||||||
|
**IKeyboardBuilder (`src/interfaces/base.py`):**
|
||||||
|
- Было: 5 методов
|
||||||
|
- Стало: 2 метода
|
||||||
|
- `get_main_keyboard()`
|
||||||
|
- `get_admin_keyboard()`
|
||||||
|
|
||||||
|
## 5. Централизация логики
|
||||||
|
|
||||||
|
### Теперь вся админская логика находится в одном месте:
|
||||||
|
- **`src/handlers/admin_panel.py`** - все обработчики админ панели
|
||||||
|
- Создание розыгрышей
|
||||||
|
- Управление участниками
|
||||||
|
- Управление победителями
|
||||||
|
- Статистика
|
||||||
|
- Настройки
|
||||||
|
|
||||||
|
### Разделение ответственности:
|
||||||
|
|
||||||
|
**main.py** - основной роутер:
|
||||||
|
- Команды `/start`, `/admin`
|
||||||
|
- Базовые callback'и (`active_lotteries`, `back_to_main`)
|
||||||
|
|
||||||
|
**admin_panel.py** - админ роутер:
|
||||||
|
- Все callback'и начинающиеся с `admin_*`
|
||||||
|
- FSM состояния для многошаговых операций
|
||||||
|
- Вся логика управления
|
||||||
|
|
||||||
|
**bot_controller.py** - бизнес-логика:
|
||||||
|
- Работа с сервисами
|
||||||
|
- Форматирование данных
|
||||||
|
- Проверка прав доступа
|
||||||
|
|
||||||
|
**ui.py** - UI компоненты:
|
||||||
|
- Построение клавиатур
|
||||||
|
- Форматирование сообщений
|
||||||
|
|
||||||
|
## 6. Результаты
|
||||||
|
|
||||||
|
### Статистика удалений:
|
||||||
|
- **Удалено строк кода:** 202
|
||||||
|
- **Добавлено строк:** 21
|
||||||
|
- **Чистый результат:** -181 строка
|
||||||
|
|
||||||
|
### Улучшения:
|
||||||
|
✅ Нет дублирующегося кода
|
||||||
|
✅ Четкое разделение ответственности
|
||||||
|
✅ Упрощенные интерфейсы
|
||||||
|
✅ Лучшая поддерживаемость
|
||||||
|
✅ Меньше потенциальных багов
|
||||||
|
|
||||||
|
### Тестирование:
|
||||||
|
✅ Бот запускается без ошибок (PID: 802748)
|
||||||
|
✅ Все роутеры подключены правильно
|
||||||
|
✅ Логика админ панели централизована
|
||||||
|
|
||||||
|
## 7. Коммиты
|
||||||
|
|
||||||
|
1. **0fdf01d** - feat: update admin panel keyboard structure and registration button logic
|
||||||
|
2. **43d46ea** - refactor: clean up unused code and duplicate handlers
|
||||||
|
|
||||||
|
## 8. Следующие шаги (рекомендации)
|
||||||
|
|
||||||
|
1. Протестировать все кнопки админ панели через Telegram
|
||||||
|
2. Использовать `ADMIN_PANEL_TESTING.md` как чек-лист
|
||||||
|
3. Проверить работу FSM состояний
|
||||||
|
4. Убедиться в корректности навигации
|
||||||
|
|
||||||
|
## 9. Примечания
|
||||||
|
|
||||||
|
- Все изменения обратно совместимы
|
||||||
|
- Логика работы не изменилась, только структура
|
||||||
|
- Бот работает стабильно
|
||||||
|
- Код стал чище и понятнее
|
||||||
@@ -547,17 +547,31 @@ class ParticipationService:
|
|||||||
"invalid_accounts": []
|
"invalid_accounts": []
|
||||||
}
|
}
|
||||||
|
|
||||||
for account_number in account_numbers:
|
for account_input in account_numbers:
|
||||||
account_number = account_number.strip()
|
account_input = account_input.strip()
|
||||||
if not account_number:
|
if not account_input:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Валидируем и форматируем номер
|
# Разделяем по пробелу: левая часть - номер карты, правая - номер счета
|
||||||
|
parts = account_input.split()
|
||||||
|
if len(parts) == 2:
|
||||||
|
card_number = parts[0] # Номер клубной карты
|
||||||
|
account_number = parts[1] # Номер счета
|
||||||
|
elif len(parts) == 1:
|
||||||
|
# Если нет пробела, считаем что это просто номер счета
|
||||||
|
card_number = None
|
||||||
|
account_number = parts[0]
|
||||||
|
else:
|
||||||
|
results["invalid_accounts"].append(account_input)
|
||||||
|
results["errors"].append(f"Неверный формат: {account_input}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Валидируем и форматируем номер счета
|
||||||
formatted_account = format_account_number(account_number)
|
formatted_account = format_account_number(account_number)
|
||||||
if not formatted_account:
|
if not formatted_account:
|
||||||
results["invalid_accounts"].append(account_number)
|
results["invalid_accounts"].append(account_input)
|
||||||
results["errors"].append(f"Неверный формат: {account_number}")
|
results["errors"].append(f"Неверный формат счета: {account_number}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Ищем пользователя по номеру счёта
|
# Ищем пользователя по номеру счёта
|
||||||
@@ -569,13 +583,19 @@ class ParticipationService:
|
|||||||
# Пробуем добавить в розыгрыш
|
# Пробуем добавить в розыгрыш
|
||||||
if await ParticipationService.add_participant(session, lottery_id, user.id):
|
if await ParticipationService.add_participant(session, lottery_id, user.id):
|
||||||
results["added"] += 1
|
results["added"] += 1
|
||||||
results["details"].append(f"Добавлен: {user.first_name} ({formatted_account})")
|
detail = f"{user.first_name} ({formatted_account})"
|
||||||
|
if card_number:
|
||||||
|
detail = f"{user.first_name} (карта: {card_number}, счёт: {formatted_account})"
|
||||||
|
results["details"].append(detail)
|
||||||
else:
|
else:
|
||||||
results["skipped"] += 1
|
results["skipped"] += 1
|
||||||
results["details"].append(f"Уже участвует: {user.first_name} ({formatted_account})")
|
detail = f"{user.first_name} ({formatted_account})"
|
||||||
|
if card_number:
|
||||||
|
detail = f"{user.first_name} (карта: {card_number}, счёт: {formatted_account})"
|
||||||
|
results["details"].append(f"Уже участвует: {detail}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
results["errors"].append(f"Ошибка с {account_number}: {str(e)}")
|
results["errors"].append(f"Ошибка с {account_input}: {str(e)}")
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -590,17 +610,31 @@ class ParticipationService:
|
|||||||
"invalid_accounts": []
|
"invalid_accounts": []
|
||||||
}
|
}
|
||||||
|
|
||||||
for account_number in account_numbers:
|
for account_input in account_numbers:
|
||||||
account_number = account_number.strip()
|
account_input = account_input.strip()
|
||||||
if not account_number:
|
if not account_input:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Валидируем и форматируем номер
|
# Разделяем по пробелу: левая часть - номер карты, правая - номер счета
|
||||||
|
parts = account_input.split()
|
||||||
|
if len(parts) == 2:
|
||||||
|
card_number = parts[0] # Номер клубной карты
|
||||||
|
account_number = parts[1] # Номер счета
|
||||||
|
elif len(parts) == 1:
|
||||||
|
# Если нет пробела, считаем что это просто номер счета
|
||||||
|
card_number = None
|
||||||
|
account_number = parts[0]
|
||||||
|
else:
|
||||||
|
results["invalid_accounts"].append(account_input)
|
||||||
|
results["errors"].append(f"Неверный формат: {account_input}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Валидируем и форматируем номер счета
|
||||||
formatted_account = format_account_number(account_number)
|
formatted_account = format_account_number(account_number)
|
||||||
if not formatted_account:
|
if not formatted_account:
|
||||||
results["invalid_accounts"].append(account_number)
|
results["invalid_accounts"].append(account_input)
|
||||||
results["errors"].append(f"Неверный формат: {account_number}")
|
results["errors"].append(f"Неверный формат счета: {account_number}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Ищем пользователя по номеру счёта
|
# Ищем пользователя по номеру счёта
|
||||||
@@ -613,13 +647,19 @@ class ParticipationService:
|
|||||||
# Пробуем удалить из розыгрыша
|
# Пробуем удалить из розыгрыша
|
||||||
if await ParticipationService.remove_participant(session, lottery_id, user.id):
|
if await ParticipationService.remove_participant(session, lottery_id, user.id):
|
||||||
results["removed"] += 1
|
results["removed"] += 1
|
||||||
results["details"].append(f"Удалён: {user.first_name} ({formatted_account})")
|
detail = f"{user.first_name} ({formatted_account})"
|
||||||
|
if card_number:
|
||||||
|
detail = f"{user.first_name} (карта: {card_number}, счёт: {formatted_account})"
|
||||||
|
results["details"].append(detail)
|
||||||
else:
|
else:
|
||||||
results["not_found"] += 1
|
results["not_found"] += 1
|
||||||
results["details"].append(f"Не участвовал: {user.first_name} ({formatted_account})")
|
detail = f"{user.first_name} ({formatted_account})"
|
||||||
|
if card_number:
|
||||||
|
detail = f"{user.first_name} (карта: {card_number}, счёт: {formatted_account})"
|
||||||
|
results["details"].append(f"Не участвовал: {detail}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
results["errors"].append(f"Ошибка с {account_number}: {str(e)}")
|
results["errors"].append(f"Ошибка с {account_input}: {str(e)}")
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user