# Система автоматического подтверждения и повторного розыгрыша ## 🎯 Обзор системы Реализована полная система автоматического подтверждения выигрышей с возможностью повторного розыгрыша для неподтвержденных призов. --- ## 🔄 Как это работает ### 1. Победитель получает уведомление После проведения розыгрыша победителю автоматически отправляется сообщение с **интерактивной кнопкой**: ``` 🎉 Поздравляем! Ваш счет выиграл! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: Главный приз 💳 Счет: 11-22-33-44-55-66-77 ⏰ У вас есть 24 часа для подтверждения! Нажмите кнопку ниже, чтобы подтвердить получение приза. Если вы не подтвердите в течение 24 часов, приз будет разыгран заново. [✅ Подтвердить получение приза] [📞 Связаться с администратором] ``` ### 2. Победитель подтверждает выигрыш Пользователь нажимает кнопку "✅ Подтвердить получение приза": **Что происходит:** - В БД устанавливается `is_claimed = True` - Сохраняется время подтверждения `claimed_at` - Победитель видит подтверждение: ``` ✅ Выигрыш успешно подтвержден! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: Главный приз 🎊 Поздравляем! Администратор свяжется с вами для передачи приза в ближайшее время. Спасибо за участие! ``` **Администраторы получают уведомление:** ``` ✅ Победитель подтвердил получение приза! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: Главный приз 👤 Победитель: Иван (@ivan) 🎫 Клубная карта: 2223 📱 Телефон: +7 900 123-45-67 💳 Счет: 11-22-33-44-55-66-77 ``` ### 3. Если победитель не подтверждает (24 часа) Администратор проверяет неподтвержденные выигрыши: ``` /check_unclaimed 1 ``` **Ответ бота:** ``` ⚠️ Неподтвержденные выигрыши в розыгрыше 'Новогодний розыгрыш': 🏆 1 место - Главный приз 👤 Иван (КК: 2223) 💳 11-22-33-44-55-66-77 ⏰ Прошло: 26 часов 🏆 3 место - Третий приз 👤 Петр (КК: 3334) 💳 22-33-44-55-66-77-88 ⏰ Прошло: 30 часов 📊 Всего неподтвержденных: 2 Используйте /redraw 1 для повторного розыгрыша ``` ### 4. Повторный розыгрыш Администратор запускает переигровку: ``` /redraw 1 ``` **Что происходит:** 1. **Система находит неподтвержденные выигрыши** (старше 24 часов) 2. **Получает пул участников** (исключая текущих победителей) 3. **Случайно выбирает новых победителей** для каждого неподтвержденного места 4. **Удаляет старых победителей** из БД 5. **Создает новых победителей** 6. **Отправляет уведомления** новым победителям (с кнопкой подтверждения) **Результат для администратора:** ``` 🔄 Повторный розыгрыш завершен! 🎯 Розыгрыш: Новогодний розыгрыш 📊 Переиграно мест: 2 🏆 1 место - Главный приз ❌ Было: 11-22-33-44-55-66-77 ✅ Стало: 99-88-77-66-55-44-33 🏆 3 место - Третий приз ❌ Было: 22-33-44-55-66-77-88 ✅ Стало: 12-34-56-78-90-12-34 📨 Новым победителям отправлены уведомления ``` **Новые победители получают** то же уведомление с кнопкой подтверждения и 24-часовым лимитом. --- ## 📋 Админские команды ### `/check_unclaimed ` Проверить неподтвержденные выигрыши старше 24 часов. **Пример:** ``` /check_unclaimed 1 ``` **Показывает:** - Список всех неподтвержденных выигрышей - Информацию о победителях - Сколько времени прошло с момента уведомления ### `/redraw ` Переиграть розыгрыш для неподтвержденных выигрышей. **Пример:** ``` /redraw 1 ``` **Требования:** - Должны быть неподтвержденные выигрыши старше 24 часов - Должны быть доступные участники (не победители) --- ## 🗄️ Изменения в базе данных ### Таблица `winners` Добавлено новое поле: - `claimed_at` (TIMESTAMP) - время подтверждения выигрыша победителем ### Миграция Файл: `migrations/versions/004_add_claimed_at.py` Применить: ```bash alembic upgrade head ``` --- ## 🔧 Технические детали ### Обработчик подтверждения **Файл:** `main.py` **Callback:** `confirm_win_{winner_id}` **Функция:** `confirm_winner_response()` **Логика:** 1. Проверяет существование выигрыша 2. Проверяет, что подтверждает владелец 3. Устанавливает `is_claimed = True` и `claimed_at = now()` 4. Обновляет сообщение победителя 5. Уведомляет всех администраторов ### Система уведомлений **Функция:** `notify_winners_async()` **Изменения:** - Добавлена кнопка "✅ Подтвердить получение приза" - Добавлено предупреждение о 24-часовом лимите - Добавлена кнопка "📞 Связаться с администратором" ### Повторный розыгрыш **Файл:** `src/handlers/redraw_handlers.py` **Команды:** - `check_unclaimed_winners()` - проверка - `redraw_lottery()` - переигровка **Алгоритм:** 1. Получает всех победителей розыгрыша 2. Фильтрует неподтвержденных (is_claimed=False, is_notified=True, >24ч) 3. Получает пул участников (исключая победителей) 4. Для каждого неподтвержденного: - Выбирает случайного участника - Удаляет старого победителя - Создает нового победителя - Отправляет уведомление --- ## 📊 Состояния выигрыша ### Таймлайн жизни выигрыша: ``` 1. Розыгрыш проведен ├─ is_notified: False ├─ is_claimed: False └─ claimed_at: NULL 2. Уведомление отправлено ├─ is_notified: True ├─ is_claimed: False └─ claimed_at: NULL 3А. Победитель подтвердил (успех) ├─ is_notified: True ├─ is_claimed: True └─ claimed_at: 2025-11-16 13:00:00 3Б. Прошло 24 часа (неудача) ├─ is_notified: True ├─ is_claimed: False ├─ claimed_at: NULL └─ ⏰ time_passed > 24h → переигровка 4. После переигровки (новый победитель) ├─ Старый победитель удален ├─ Создан новый победитель ├─ is_notified: True (после отправки) ├─ is_claimed: False └─ claimed_at: NULL → снова 24 часа ``` --- ## ⚠️ Важные моменты ### Безопасность 1. **Проверка владельца**: Только владелец счета может подтвердить выигрыш 2. **Повторное подтверждение**: Если выигрыш уже подтвержден, показывается соответствующее сообщение 3. **Права администратора**: Только админы могут запускать `/redraw` ### Ограничения 1. **24-часовой лимит**: Жестко закодирован, но легко изменить в коде 2. **Пул участников**: Если все участники уже победители, переигровка невозможна 3. **Уникальность**: Один счет не может выиграть дважды в одном розыгрыше ### Отказоустойчивость 1. **Уведомления**: Если не удается отправить - продолжает работу 2. **Транзакции**: Все изменения в БД атомарны 3. **Логирование**: Все действия записываются в лог --- ## 🎯 Типичные сценарии ### Сценарий 1: Все подтвердили ``` 1. Розыгрыш → 3 победителя 2. Все 3 нажали кнопку подтверждения 3. Админ: /check_unclaimed 1 → "✅ Все победители подтвердили выигрыш" 4. Приз передается всем победителям ``` ### Сценарий 2: Один не подтвердил ``` 1. Розыгрыш → 3 победителя 2. 2 подтвердили, 1 игнорирует 3. Через 25 часов админ: /check_unclaimed 1 → "⚠️ 1 неподтвержденный выигрыш" 4. Админ: /redraw 1 5. Система переигрывает 1 место 6. Новый победитель получает уведомление 7. У нового победителя снова 24 часа ``` ### Сценарий 3: Множественная переигровка ``` 1. Розыгрыш → 5 победителей 2. 3 подтвердили, 2 игнорируют 3. Через 25 часов: /redraw 1 4. 2 новых победителя выбраны 5. Один из новых тоже игнорирует 6. Через 25 часов: /redraw 1 снова 7. Выбран еще один новый победитель ``` --- ## 📈 Статистика и мониторинг ### Проверка статуса ``` /winner_status 1 ``` Покажет: - ✅ Подтвержденные выигрыши (с is_claimed=True) - ⏳ Ожидающие подтверждения (с is_claimed=False) - 📨 Статус уведомления (is_notified) ### SQL запросы для админа **Найти все неподтвержденные старше 24 часов:** ```sql SELECT w.*, l.title FROM winners w JOIN lotteries l ON w.lottery_id = l.id WHERE w.is_notified = TRUE AND w.is_claimed = FALSE AND w.created_at < NOW() - INTERVAL '24 hours'; ``` **Статистика по подтверждениям:** ```sql SELECT lottery_id, COUNT(*) as total_winners, SUM(CASE WHEN is_claimed THEN 1 ELSE 0 END) as confirmed, SUM(CASE WHEN NOT is_claimed THEN 1 ELSE 0 END) as unconfirmed FROM winners WHERE is_notified = TRUE GROUP BY lottery_id; ``` --- ## 🚀 Использование ### Для администратора 1. **После розыгрыша**: Ничего не делать - система отправит уведомления 2. **Через 24-30 часов**: Проверить `/check_unclaimed ` 3. **Если есть неподтвержденные**: Запустить `/redraw ` 4. **Повторить** при необходимости ### Для победителя 1. **Получить уведомление** с кнопкой 2. **Нажать "✅ Подтвердить"** 3. **Дождаться связи с админом** 4. **Получить приз** --- ## 💡 Рекомендации ### Оптимальные настройки - **Лимит подтверждения**: 24 часа (можно увеличить до 48ч) - **Частота проверки**: 1-2 раза в день - **Уведомления**: Включить push-уведомления в боте ### Коммуникация с пользователями После розыгрыша отправьте общее сообщение: ``` 🎉 Розыгрыш завершен! Если вы выиграли, вам придет сообщение с кнопкой подтверждения. ⏰ У вас будет 24 часа чтобы подтвердить выигрыш! Если не подтвердите - приз будет переигран. ``` --- ## 🔮 Возможные улучшения 1. **Напоминания**: Отправка напоминания за 2 часа до истечения срока 2. **Гибкий лимит**: Разные лимиты для разных типов призов 3. **История**: Логирование всех переигровок 4. **Статистика**: Процент подтверждений, среднее время подтверждения 5. **Автоматизация**: Cron-задача для автоматической переигровки --- ## ✅ Преимущества системы - 🤖 **Полная автоматизация**: Минимум ручной работы для админа - ⏱️ **Справедливость**: Четкий дедлайн для всех - 🔄 **Эффективность**: Призы не "зависают" у неактивных победителей - 📊 **Прозрачность**: Полная история всех действий - 🛡️ **Безопасность**: Только владелец может подтвердить - 💬 **UX**: Простая кнопка вместо сложной верификации --- ## 📞 Поддержка Если что-то пошло не так: 1. Проверьте логи бота 2. Проверьте состояние БД (claimed_at, is_notified, is_claimed) 3. Используйте `/winner_status ` для диагностики 4. При критических ошибках - используйте `/verify_winner` для ручного подтверждения