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
280 lines
11 KiB
Markdown
280 lines
11 KiB
Markdown
# Подтверждение выигрышей по счетам
|
||
|
||
## 🎯 Концепция
|
||
|
||
Система подтверждения выигрышей работает **на уровне счетов**, а не пользователей.
|
||
|
||
### Основные принципы:
|
||
|
||
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` - Руководство администратора
|