feat: Система автоматического подтверждения выигрышей с поддержкой множественных счетов
Some checks reported errors
continuous-integration/drone/push Build encountered an error

Основные изменения:

 Новые функции:
- Система регистрации пользователей с множественными счетами
- Автоматическое подтверждение выигрышей через inline-кнопки
- Механизм переигровки для неподтвержденных выигрышей (24 часа)
- Подтверждение на уровне счетов (каждый счет подтверждается отдельно)
- Скрипт полной очистки базы данных

🔧 Технические улучшения:
- Исправлена ошибка MissingGreenlet при lazy loading (добавлен joinedload/selectinload)
- Добавлено поле claimed_at для отслеживания времени подтверждения
- Пакетное добавление счетов с выбором розыгрыша
- Проверка владения конкретным счетом при подтверждении

📚 Документация:
- docs/AUTO_CONFIRM_SYSTEM.md - Полная документация системы подтверждения
- docs/ACCOUNT_BASED_CONFIRMATION.md - Подтверждение на уровне счетов
- docs/REGISTRATION_SYSTEM.md - Система регистрации
- docs/ADMIN_COMMANDS.md - Команды администратора
- docs/CLEAR_DATABASE.md - Очистка БД
- docs/QUICK_GUIDE.md - Быстрое начало
- docs/UPDATE_LOG.md - Журнал обновлений

🗄️ База данных:
- Миграция 003: Таблицы accounts, winner_verifications
- Миграция 004: Поле claimed_at в таблице winners
- Скрипт scripts/clear_database.py для полной очистки

🎮 Новые команды:
Админские:
- /check_unclaimed <lottery_id> - Проверка неподтвержденных выигрышей
- /redraw <lottery_id> - Повторный розыгрыш
- /add_accounts - Пакетное добавление счетов
- /list_accounts <telegram_id> - Список счетов пользователя

Пользовательские:
- /register - Регистрация с вводом данных
- /my_account - Просмотр своих счетов
- Callback confirm_win_{id} - Подтверждение выигрыша

🛠️ Makefile:
- make clear-db - Очистка всех данных из БД (с подтверждением)

🔒 Безопасность:
- Проверка владения счетом при подтверждении
- Защита от подтверждения чужих счетов
- Независимое подтверждение каждого выигрышного счета

📊 Логика работы:
1. Пользователь регистрируется и добавляет счета
2. Счета участвуют в розыгрыше
3. Победители получают уведомление с кнопкой подтверждения
4. Каждый счет подтверждается отдельно (24 часа на подтверждение)
5. Неподтвержденные выигрыши переигрываются через /redraw
This commit is contained in:
2025-11-16 14:01:30 +09:00
parent 31c4c5382a
commit 505d26f0e9
21 changed files with 4217 additions and 68 deletions

318
docs/ADMIN_COMMANDS.md Normal file
View File

@@ -0,0 +1,318 @@
# Админские команды - Руководство
## 🎯 Управление счетами
### `/add_account` - Добавить счет пользователю
Привязывает счет к зарегистрированному пользователю по клубной карте.
**Формат:**
```
/add_account <club_card> <account_number>
```
**Пример:**
```
/add_account 2223 11-22-33-44-55-66-77
```
**Что происходит:**
- Система проверяет существование пользователя с указанной клубной картой
- Создает новую запись счета в таблице `accounts`
- Отправляет уведомление владельцу о добавлении счета
- Счет становится активным и может участвовать в розыгрышах
**Возможные ошибки:**
- "Пользователь с клубной картой X не найден" - пользователь не зарегистрирован
- "Счет уже существует" - этот номер счета уже привязан к другому пользователю
---
### `/remove_account` - Деактивировать счет
Делает счет неактивным (не удаляет из БД).
**Формат:**
```
/remove_account <account_number>
```
**Пример:**
```
/remove_account 11-22-33-44-55-66-77
```
**Что происходит:**
- Устанавливает флаг `is_active = False`
- Счет остается в БД, но не может участвовать в новых розыгрышах
- История участия сохраняется
---
## 🏆 Управление выигрышами
### `/verify_winner` - Подтвердить выигрыш
Подтверждает выигрыш по коду верификации пользователя.
**Формат:**
```
/verify_winner <verification_code> <lottery_id>
```
**Пример:**
```
/verify_winner AB12CD34 1
```
**Процесс верификации:**
1. Пользователь сообщает администратору свой код верификации
2. Администратор проверяет, что пользователь является победителем указанного розыгрыша
3. Система устанавливает флаг `is_claimed = True` для выигрыша
4. Отправляется уведомление победителю о подтверждении
**Что происходит:**
- Поиск пользователя по коду верификации
- Проверка наличия выигрыша в указанном розыгрыше
- Установка флага `is_claimed = True`
- Отправка подтверждающего сообщения победителю
**Возможные ошибки:**
- "Розыгрыш не найден" - неверный lottery_id
- "Выигрыш не найден" - неверный код или пользователь не победитель
- "Выигрыш уже был подтвержден" - повторная попытка подтверждения
---
### `/winner_status` - Статус победителей
Показывает всех победителей розыгрыша и их статус подтверждения.
**Формат:**
```
/winner_status <lottery_id>
```
**Пример:**
```
/winner_status 1
```
**Отображаемая информация:**
- 🏆 Место и приз
- 👤 Имя и клубная карта победителя
- 💳 Номер счета (если участвовал через счет)
- ✅ Статус подтверждения (подтвержден / ожидает)
- 📨 Статус уведомления (отправлено / нет)
**Статусы:**
- ✅ - Выигрыш подтвержден (`is_claimed = True`)
- ⏳ - Ожидает подтверждения (`is_claimed = False`)
- 📨 - Уведомление отправлено (`is_notified = True`)
- 📭 - Уведомление не отправлено (`is_notified = False`)
---
## 👤 Информация о пользователе
### `/user_info` - Информация о пользователе
Показывает полную информацию о пользователе по клубной карте.
**Формат:**
```
/user_info <club_card>
```
**Пример:**
```
/user_info 2223
```
**Отображаемая информация:**
- 🎫 Клубная карта
- 👤 Имя и Telegram username
- 📞 Телефон (если указан)
- 🔑 Код верификации
- 📅 Дата регистрации
- 💳 Список всех счетов (активные и неактивные)
- 🏆 История выигрышей
---
## 🔄 Автоматические уведомления
При проведении розыгрыша (`/conduct` через кнопку) система автоматически:
1. **Определяет владельцев счетов-победителей**
- Ищет запись в таблице `accounts`
- Находит владельца через `owner_id`
2. **Создает токен верификации**
- Генерирует уникальный токен для каждого выигрыша
- Устанавливает срок действия 24 часа
- Сохраняет в таблице `winner_verifications`
3. **Отправляет уведомление победителю**
```
🎉 Поздравляем! Ваш счет выиграл!
🎯 Розыгрыш: Название розыгрыша
🏆 Место: 1
🎁 Приз: Приз первого места
💳 Счет: 11-22-33-44-55-66-77
🔑 Ваш код верификации: AB12CD34
Для получения приза свяжитесь с администратором
и предоставьте этот код.
```
4. **Устанавливает флаг уведомления**
- `is_notified = True` в таблице `winners`
---
## 🔐 Система верификации
### Как это работает:
1. **При регистрации пользователя:**
- Генерируется уникальный 8-символьный код (например, `AB12CD34`)
- Сохраняется в `users.verification_code`
- Пользователь может посмотреть свой код через `/my_code`
2. **При выигрыше:**
- Владельцу счета отправляется сообщение с его кодом верификации
- Создается токен в таблице `winner_verifications`
3. **При подтверждении выигрыша:**
- Администратор запрашивает код у победителя
- Вводит команду `/verify_winner AB12CD34 1`
- Система проверяет соответствие кода и наличие выигрыша
- Устанавливает `is_claimed = True`
### Преимущества:
- 🔒 **Безопасность**: Только владелец знает свой код
- ✅ **Проверка**: Невозможно подтвердить чужой выигрыш
- 📊 **Отслеживание**: Полная история подтверждений
- ⏱️ **Контроль**: Токены имеют срок действия
---
## 📊 Типичные сценарии
### Сценарий 1: Новый пользователь с двумя счетами
```
1. Пользователь: /start → "Зарегистрироваться"
2. Пользователь: Вводит клубную карту "2223"
3. Пользователь: Вводит телефон или пропускает
4. Система: Показывает код верификации "AB12CD34"
5. Админ: /add_account 2223 11-22-33-44-55-66-77
6. Админ: /add_account 2223 88-99-00-11-22-33-44
7. Пользователь: /my_accounts
→ Видит оба счета
```
### Сценарий 2: Проведение розыгрыша и подтверждение
```
1. Админ: Создает розыгрыш через интерфейс
2. Счета участвуют автоматически
3. Админ: Нажимает "Провести розыгрыш"
4. Система: Автоматически отправляет уведомления:
"🎉 Поздравляем! Ваш счет выиграл!
💳 Счет: 11-22-33-44-55-66-77
🔑 Ваш код верификации: AB12CD34"
5. Победитель: Связывается с админом, называет код "AB12CD34"
6. Админ: /verify_winner AB12CD34 1
7. Система: Подтверждает выигрыш, отправляет уведомление победителю
```
### Сценарий 3: Проверка статуса всех победителей
```
1. Админ: /winner_status 1
Результат:
🏆 Победители розыгрыша 'Новогодний розыгрыш':
✅ 1 место - Главный приз
👤 Иван (КК: 2223)
💳 11-22-33-44-55-66-77
✅ Подтвержден
⏳ 2 место - Второй приз
👤 Петр (КК: 3334)
💳 22-33-44-55-66-77-88
⏳ Ожидает подтверждения
```
---
## 🛠️ Техническая информация
### Таблицы базы данных:
**accounts** - Счета пользователей
- `account_number` - Номер счета (формат XX-XX-XX-XX-XX-XX-XX)
- `owner_id` - ID владельца (FK → users.id)
- `is_active` - Активен ли счет
- `created_at` - Дата создания
**winner_verifications** - Токены верификации выигрышей
- `winner_id` - ID выигрыша (FK → winners.id)
- `verification_token` - Уникальный токен
- `is_verified` - Подтвержден ли
- `verified_at` - Время подтверждения
- `expires_at` - Срок действия (24 часа)
**winners** - Победители (расширенная)
- Добавлены поля: `is_notified`, `is_claimed`
**users** - Пользователи (расширенная)
- Добавлены поля: `club_card_number`, `phone`, `is_registered`, `verification_code`
---
## 📝 Полезные команды для пользователей
- `/start` - Главное меню / регистрация
- `/my_code` - Показать свой код верификации
- `/my_accounts` - Список моих счетов
---
## ⚠️ Важные замечания
1. **Код верификации** - строго конфиденциальная информация
2. **Один счет** = один владелец (нельзя передать счет другому)
3. **Деактивация счета** - не удаляет историю участия
4. **Токены верификации** - действуют 24 часа
5. **Уведомления** - отправляются автоматически только если пользователь зарегистрирован
---
## 🆘 Решение проблем
**Пользователь не получил уведомление о выигрыше:**
- Проверить `/winner_status <lottery_id>` - должна быть отметка 📨
- Возможно, пользователь заблокировал бота
- Проверить telegram_id пользователя через `/user_info`
**Не получается подтвердить выигрыш:**
- Проверить код верификации: `/user_info <club_card>`
- Убедиться что lottery_id верный
- Проверить что выигрыш еще не подтвержден
**Счет не добавляется:**
- Убедиться что пользователь зарегистрирован
- Проверить формат номера счета (7 пар цифр через дефис)
- Проверить что счет уникален (не добавлен другому пользователю)