# Подтверждение выигрышей по счетам ## 🎯 Концепция Система подтверждения выигрышей работает **на уровне счетов**, а не пользователей. ### Основные принципы: 1. **Один пользователь = Много счетов** - У клиента может быть несколько счетов (11-22-33..., 44-55-66..., и т.д.) - Каждый счет участвует в розыгрыше независимо 2. **Один счет = Один выигрыш = Одно подтверждение** - Если счет `11-22-33-44-55-66-77` выиграл 1 место - требуется подтверждение - Если счет `44-55-66-77-88-99-00` выиграл 3 место - требуется отдельное подтверждение - Даже если оба счета принадлежат одному клиенту 3. **Независимое подтверждение** - Каждый выигрышный счет подтверждается отдельной кнопкой - Подтверждение одного счета не влияет на другие - У каждого счета свой 24-часовой лимит ## 📱 Как это работает для пользователя ### Сценарий: У клиента 3 счета, выиграли 2 **Счета клиента:** - `11-22-33-44-55-66-77` ✅ Выиграл 1 место (iPhone 15) - `22-33-44-55-66-77-88` ❌ Не выиграл - `33-44-55-66-77-88-99` ✅ Выиграл 3 место (AirPods Pro) **Клиент получает 2 сообщения:** ### Сообщение 1: ``` 🎉 Поздравляем! Ваш счет выиграл! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: iPhone 15 💳 Выигрышный счет: 11-22-33-44-55-66-77 ⏰ У вас есть 24 часа для подтверждения! Нажмите кнопку ниже, чтобы подтвердить получение приза по этому счету. Если вы не подтвердите в течение 24 часов, приз будет разыгран заново. ℹ️ Если у вас несколько выигрышных счетов, подтвердите каждый из них отдельно. [✅ Подтвердить счет 11-22-33-44-55-66-77] [📞 Связаться с администратором] ``` ### Сообщение 2: ``` 🎉 Поздравляем! Ваш счет выиграл! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 3 🎁 Приз: AirPods Pro 💳 Выигрышный счет: 33-44-55-66-77-88-99 ⏰ У вас есть 24 часа для подтверждения! [✅ Подтвердить счет 33-44-55-66-77-88-99] [📞 Связаться с администратором] ``` ### Действия клиента: 1. **Нажимает первую кнопку** → Счет `11-22-33-44-55-66-77` подтвержден ✅ 2. **Нажимает вторую кнопку** → Счет `33-44-55-66-77-88-99` подтвержден ✅ ## 🔒 Безопасность ### Проверка владения счетом При нажатии кнопки подтверждения система проверяет: ```python # Получаем владельца КОНКРЕТНОГО счета owner = await AccountService.get_account_owner(session, winner.account_number) # Проверяем что текущий пользователь - владелец ЭТОГО счета if not owner or owner.telegram_id != callback.from_user.id: await callback.answer( f"❌ Счет {winner.account_number} вам не принадлежит", show_alert=True ) return ``` ### Что НЕ может сделать пользователь: ❌ Подтвердить чужой счет ❌ Подтвердить счет, который ему не принадлежит ❌ Подтвердить один счет дважды ### Что может сделать пользователь: ✅ Подтвердить только свои счета ✅ Подтвердить каждый свой выигрышный счет отдельно ✅ Видеть номер счета на каждой кнопке ## 🎊 После подтверждения ### Сообщение пользователю: ``` ✅ Выигрыш успешно подтвержден! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: iPhone 15 💳 Счет: 11-22-33-44-55-66-77 🎊 Поздравляем! Администратор свяжется с вами для передачи приза в ближайшее время. Спасибо за участие! ``` ### Уведомление администратору: ``` ✅ Победитель подтвердил получение приза! 🎯 Розыгрыш: Новогодний розыгрыш 🏆 Место: 1 🎁 Приз: iPhone 15 💳 Подтвержденный счет: 11-22-33-44-55-66-77 👤 Владелец: Иван Петров (@ivan) 🎫 Клубная карта: 2223 📱 Телефон: +7 900 123-45-67 ``` ## 📊 База данных ### Таблица `winners` Каждая запись = один выигрышный счет: ```sql id | lottery_id | account_number | place | prize | is_claimed | claimed_at ---|------------|-----------------------|-------|------------|------------|------------------ 1 | 5 | 11-22-33-44-55-66-77 | 1 | iPhone 15 | TRUE | 2025-11-16 14:00 2 | 5 | 33-44-55-66-77-88-99 | 3 | AirPods | TRUE | 2025-11-16 14:05 3 | 5 | 55-66-77-88-99-00-11 | 2 | MacBook | FALSE | NULL ``` ### Ключевые поля: - `account_number` - конкретный выигрышный счет - `is_claimed` - подтвержден ли ЭТОТ счет - `claimed_at` - когда ЭТОТ счет был подтвержден ## 🔄 Повторный розыгрыш Если счет не подтвержден в течение 24 часов: 1. **Админ проверяет**: `/check_unclaimed 5` ``` ⚠️ Неподтвержденные выигрыши: 🏆 2 место - MacBook 💳 55-66-77-88-99-00-11 ⏰ Прошло: 26 часов ``` 2. **Админ переигрывает**: `/redraw 5` - Удаляется Winner с `account_number = 55-66-77-88-99-00-11` - Выбирается новый случайный счет - Новому владельцу счета отправляется уведомление - Новый владелец получает свои 24 часа ## 💡 Преимущества подхода ### ✅ Для пользователей: 1. **Понятность** - видят конкретный номер счета на кнопке 2. **Контроль** - могут подтверждать счета независимо 3. **Гибкость** - один счет подтвердил, другой нет (если забыл) ### ✅ Для администраторов: 1. **Точность** - знают какой именно счет подтвержден 2. **Прозрачность** - видят все действия по каждому счету 3. **Справедливость** - переиграть можно конкретный неподтвержденный счет ### ✅ Для системы: 1. **Масштабируемость** - неограниченное количество счетов у одного пользователя 2. **Независимость** - каждый счет живет своей жизнью 3. **Целостность** - нет конфликтов между разными выигрышами ## 🔍 Примеры использования ### Пример 1: Один пользователь, два выигрыша ``` Клиент: Иван Петров (КК: 2223) Счета: - 11-22-33-44-55-66-77 → Выиграл 1 место ✅ Подтвержден - 22-33-44-55-66-77-88 → Выиграл 3 место ✅ Подтвержден Результат: Иван получит 2 приза ``` ### Пример 2: Частичное подтверждение ``` Клиент: Мария Сидорова (КК: 3334) Счета: - 33-44-55-66-77-88-99 → Выиграл 2 место ✅ Подтвержден - 44-55-66-77-88-99-00 → Выиграл 4 место ❌ Не подтвержден (> 24ч) Результат: - Мария получит приз за 2 место - 4 место будет переиграно ``` ### Пример 3: Полная неявка ``` Клиент: Петр Иванов (КК: 5556) Счета: - 55-66-77-88-99-00-11 → Выиграл 1 место ❌ Не подтвержден - 66-77-88-99-00-11-22 → Выиграл 2 место ❌ Не подтвержден Результат: Оба места будут переиграны отдельно ``` ## 📝 Технические детали ### Callback данные ```python # Формат: confirm_win_{winner_id} callback_data = f"confirm_win_{winner.id}" # winner.id - уникальный ID записи в таблице winners # Каждый счет-выигрыш имеет свой winner_id ``` ### Проверка при подтверждении ```python # 1. Получаем winner по ID winner = await session.get(Winner, winner_id) # 2. Проверяем что счет принадлежит пользователю owner = await AccountService.get_account_owner(session, winner.account_number) if owner.telegram_id != current_user_id: return "Не ваш счет" # 3. Подтверждаем ЭТОТ счет winner.is_claimed = True winner.claimed_at = datetime.now(timezone.utc) await session.commit() ``` ## 🎓 Выводы Подход "счет = выигрыш" обеспечивает: - 🎯 **Точность** - подтверждается конкретный счет, а не абстрактный выигрыш - 🔒 **Безопасность** - только владелец счета может подтвердить - 📊 **Масштабируемость** - неограниченное количество счетов и выигрышей - 👥 **Справедливость** - каждый счет обрабатывается независимо - 💡 **Прозрачность** - всегда понятно какой именно счет подтверждается --- ## 📞 См. также - `AUTO_CONFIRM_SYSTEM.md` - Полная документация системы подтверждения - `REGISTRATION_SYSTEM.md` - Система регистрации счетов - `ADMIN_GUIDE.md` - Руководство администратора