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
11 KiB
11 KiB
Подтверждение выигрышей по счетам
🎯 Концепция
Система подтверждения выигрышей работает на уровне счетов, а не пользователей.
Основные принципы:
-
Один пользователь = Много счетов
- У клиента может быть несколько счетов (11-22-33..., 44-55-66..., и т.д.)
- Каждый счет участвует в розыгрыше независимо
-
Один счет = Один выигрыш = Одно подтверждение
- Если счет
11-22-33-44-55-66-77выиграл 1 место - требуется подтверждение - Если счет
44-55-66-77-88-99-00выиграл 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]
[📞 Связаться с администратором]
Действия клиента:
- Нажимает первую кнопку → Счет
11-22-33-44-55-66-77подтвержден ✅ - Нажимает вторую кнопку → Счет
33-44-55-66-77-88-99подтвержден ✅
🔒 Безопасность
Проверка владения счетом
При нажатии кнопки подтверждения система проверяет:
# Получаем владельца КОНКРЕТНОГО счета
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
Каждая запись = один выигрышный счет:
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 часов:
-
Админ проверяет:
/check_unclaimed 5⚠️ Неподтвержденные выигрыши: 🏆 2 место - MacBook 💳 55-66-77-88-99-00-11 ⏰ Прошло: 26 часов -
Админ переигрывает:
/redraw 5- Удаляется Winner с
account_number = 55-66-77-88-99-00-11 - Выбирается новый случайный счет
- Новому владельцу счета отправляется уведомление
- Новый владелец получает свои 24 часа
- Удаляется Winner с
💡 Преимущества подхода
✅ Для пользователей:
- Понятность - видят конкретный номер счета на кнопке
- Контроль - могут подтверждать счета независимо
- Гибкость - один счет подтвердил, другой нет (если забыл)
✅ Для администраторов:
- Точность - знают какой именно счет подтвержден
- Прозрачность - видят все действия по каждому счету
- Справедливость - переиграть можно конкретный неподтвержденный счет
✅ Для системы:
- Масштабируемость - неограниченное количество счетов у одного пользователя
- Независимость - каждый счет живет своей жизнью
- Целостность - нет конфликтов между разными выигрышами
🔍 Примеры использования
Пример 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 данные
# Формат: confirm_win_{winner_id}
callback_data = f"confirm_win_{winner.id}"
# winner.id - уникальный ID записи в таблице winners
# Каждый счет-выигрыш имеет свой winner_id
Проверка при подтверждении
# 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- Руководство администратора