@@ -69,6 +69,10 @@ class AdminStates(StatesGroup):
remove_participant_bulk_accounts = State ( )
participant_search = State ( )
# Добавление/удаление участников в конкретном розыгрыше
add_to_lottery_user = State ( )
remove_from_lottery_user = State ( )
# Установка победителей
set_winner_lottery = State ( )
set_winner_place = State ( )
@@ -124,6 +128,12 @@ def get_admin_main_keyboard() -> InlineKeyboardMarkup:
def get_lottery_management_keyboard ( ) - > InlineKeyboardMarkup :
""" Клавиатура управления розыгрышами """
buttons = [
<< << << < HEAD
[ InlineKeyboardButton ( text = " ➕ Создать розыгрыш" , callback_data = " admin_create_lottery " ) ] ,
[ InlineKeyboardButton ( text = " <EFBFBD> Список всех розыгрышей" , callback_data = " admin_list_all_lotteries " ) ] ,
[ InlineKeyboardButton ( text = " 🎭 Настройка отображения победителей " , callback_data = " admin_winner_display_settings " ) ] ,
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = " admin_panel " ) ]
== == == =
[ InlineKeyboardButton ( text = " ✨ Создать " , callback_data = " admin_create_lottery " ) ,
InlineKeyboardButton ( text = " ✏️ Редактировать " , callback_data = " admin_edit_lottery " ) ] ,
[ InlineKeyboardButton ( text = " 📜 Список всех " , callback_data = " admin_list_all_lotteries " ) ] ,
@@ -131,6 +141,7 @@ def get_lottery_management_keyboard() -> InlineKeyboardMarkup:
[ InlineKeyboardButton ( text = " ✅ Завершить " , callback_data = " admin_finish_lottery " ) ,
InlineKeyboardButton ( text = " 🗑️ Удалить " , callback_data = " admin_delete_lottery " ) ] ,
[ InlineKeyboardButton ( text = " ◀️ Назад " , callback_data = " admin_panel " ) ]
>> >> >> > v2_functions
]
return InlineKeyboardMarkup ( inline_keyboard = buttons )
@@ -153,12 +164,19 @@ def get_participant_management_keyboard() -> InlineKeyboardMarkup:
def get_winner_management_keyboard ( ) - > InlineKeyboardMarkup :
""" Клавиатура управления победителями """
buttons = [
<< << << < HEAD
[ InlineKeyboardButton ( text = " 👑 Установить победителя " , callback_data = " admin_set_manual_winner " ) ] ,
[ InlineKeyboardButton ( text = " 📝 Изменить победителя " , callback_data = " admin_edit_winner " ) ] ,
[ InlineKeyboardButton ( text = " ❌ Удалить победителя " , callback_data = " admin_remove_winner " ) ] ,
[ InlineKeyboardButton ( text = " Назад " , callback_data = " admin_panel " ) ]
== == == =
[ InlineKeyboardButton ( text = " 🏆 Установить вручную " , callback_data = " admin_set_manual_winner " ) ] ,
[ InlineKeyboardButton ( text = " ✏️ Изменить " , callback_data = " admin_edit_winner " ) ,
InlineKeyboardButton ( text = " ❌ Удалить " , callback_data = " admin_remove_winner " ) ] ,
[ InlineKeyboardButton ( text = " 📜 Список победителей " , callback_data = " admin_list_winners " ) ] ,
[ InlineKeyboardButton ( text = " 👁️ Настройка отображения " , callback_data = " admin_winner_display_settings " ) ] ,
[ InlineKeyboardButton ( text = " ◀️ Назад " , callback_data = " admin_panel " ) ]
>> >> >> > v2_functions
]
return InlineKeyboardMarkup ( inline_keyboard = buttons )
@@ -571,15 +589,32 @@ async def show_lottery_detail(callback: CallbackQuery):
buttons = [ ]
if not lottery . is_completed :
# Розыгрыш ещё не проведён
buttons . extend ( [
<< << << < HEAD
[ InlineKeyboardButton ( text = " 🎲 Провести розыгрыш " , callback_data = f " admin_conduct_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 👑 Установить победителя " , callback_data = f " admin_set_winner_ { lottery_id } " ) ] ,
] )
else :
# Розыгрыш завершён - показываем управление победителями
buttons . extend ( [
[ InlineKeyboardButton ( text = " ✅ Проверка победителей " , callback_data = f " admin_check_winners_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 🔄 Провести повторно " , callback_data = f " admin_redraw_ { lottery_id } " ) ] ,
== == == =
[ InlineKeyboardButton ( text = " 🏆 Установить победителя " , callback_data = f " admin_set_winner_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 🎰 Провести розыгрыш " , callback_data = f " admin_conduct_ { lottery_id } " ) ] ,
>> >> >> > v2_functions
] )
buttons . extend ( [
[ InlineKeyboardButton ( text = " 📝 Редактировать " , callback_data = f " admin_edit_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 👥 Участники " , callback_data = f " admin_participants_ { lottery_id } " ) ] ,
<< << << < HEAD
[ InlineKeyboardButton ( text = " 🗑️ Удалить " , callback_data = f " admin_del_lottery_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 🔙 К списку " , callback_data = " admin_list_all_lotteries " ) ]
== == == =
[ InlineKeyboardButton ( text = " ◀️ К списку " , callback_data = " admin_list_all_lotteries " ) ]
>> >> >> > v2_functions
] )
await callback . message . edit_text ( text , reply_markup = InlineKeyboardMarkup ( inline_keyboard = buttons ) )
@@ -1447,6 +1482,579 @@ async def process_bulk_remove_participant(message: Message, state: FSMContext):
)
# ======================
# ДОБАВЛЕНИЕ/УДАЛЕНИЕ УЧАСТНИКОВ В К О Н К Р Е Т Н О М РОЗЫГРЫШЕ
# ======================
@admin_router.callback_query ( F . data . startswith ( " admin_add_to_ " ) )
async def add_participant_to_lottery ( callback : CallbackQuery , state : FSMContext ) :
""" Добавление участника в конкретный розыгрыш """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
await state . update_data ( add_to_lottery_id = lottery_id )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
text = f " ➕ Добавление участника\n \n "
text + = f " 🎯 Розыгрыш: { lottery . title } \n \n "
text + = " Введите данные участника: \n "
text + = " • Telegram ID (число) \n "
text + = " • @username \n "
text + = " • Номер счета (XX-XX-XX-XX-XX-XX-XX) "
await callback . message . edit_text (
text ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ❌ Отмена " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
await state . set_state ( AdminStates . add_to_lottery_user )
@admin_router.message ( StateFilter ( AdminStates . add_to_lottery_user ) )
async def process_add_to_lottery ( message : Message , state : FSMContext ) :
""" Обработка добавления участника в конкретный розыгрыш """
if not is_admin ( message . from_user . id ) :
await message . answer ( " ❌ Недостаточно прав " )
return
data = await state . get_data ( )
lottery_id = data . get ( ' add_to_lottery_id ' )
user_input = message . text . strip ( )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await message . answer ( " ❌ Розыгрыш не найден " )
await state . clear ( )
return
# Определяем тип ввода
user = None
account_number = None
if user_input . startswith ( ' @ ' ) :
# Username
username = user_input [ 1 : ]
user = await UserService . get_user_by_username ( session , username )
elif user_input . isdigit ( ) :
# Telegram ID
telegram_id = int ( user_input )
user = await UserService . get_user_by_telegram_id ( session , telegram_id )
elif ' - ' in user_input :
# Номер счета
from src . utils . account_utils import parse_accounts_from_message
accounts = parse_accounts_from_message ( user_input )
if accounts :
account_number = accounts [ 0 ]
if not user and not account_number :
await message . answer (
" ❌ Н е удалось найти пользователя или распознать счет. \n "
" Пользователь должен запустить бота командой /start " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
await state . clear ( )
return
# Добавляем участника
if user :
success = await ParticipationService . add_participant ( session , lottery_id , user . id )
name = f " @ { user . username } " if user . username else f " { user . first_name } (ID: { user . telegram_id } ) "
else :
# Добавление по номеру счета
from sqlalchemy import select
from . . core . models import Participation
# Проверяем, не добавлен ли уже этот счет
existing = await session . execute (
select ( Participation ) . where (
Participation . lottery_id == lottery_id ,
Participation . account_number == account_number
)
)
if existing . scalar_one_or_none ( ) :
await message . answer (
f " ⚠️ Счет { account_number } уже участвует в этом розыгрыше " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
await state . clear ( )
return
participation = Participation ( lottery_id = lottery_id , account_number = account_number )
session . add ( participation )
await session . commit ( )
success = True
name = f " Счет: { account_number } "
await state . clear ( )
if success :
await message . answer (
f " ✅ Участник добавлен! \n \n "
f " 👤 { name } \n "
f " 🎯 Розыгрыш: { lottery . title } " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ➕ Добавить ещё" , callback_data = f " admin_add_to_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 👥 К участникам " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
else :
await message . answer (
f " ⚠️ Участник уже добавлен в этот розыгрыш " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
@admin_router.callback_query ( F . data . startswith ( " admin_remove_from_ " ) )
async def remove_participant_from_lottery ( callback : CallbackQuery , state : FSMContext ) :
""" Удаление участника из конкретного розыгрыша """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
await state . update_data ( remove_from_lottery_id = lottery_id )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
participants_count = await ParticipationService . get_participants_count ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
text = f " ➖ Удаление участника\n \n "
text + = f " 🎯 Розыгрыш: { lottery . title } \n "
text + = f " 👥 Участников: { participants_count } \n \n "
text + = " Введите данные участника для удаления: \n "
text + = " • Telegram ID (число) \n "
text + = " • @username \n "
text + = " • Номер счета (XX-XX-XX-XX-XX-XX-XX) "
await callback . message . edit_text (
text ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ❌ Отмена " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
await state . set_state ( AdminStates . remove_from_lottery_user )
@admin_router.message ( StateFilter ( AdminStates . remove_from_lottery_user ) )
async def process_remove_from_lottery ( message : Message , state : FSMContext ) :
""" Обработка удаления участника из конкретного розыгрыша """
if not is_admin ( message . from_user . id ) :
await message . answer ( " ❌ Недостаточно прав " )
return
data = await state . get_data ( )
lottery_id = data . get ( ' remove_from_lottery_id ' )
user_input = message . text . strip ( )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await message . answer ( " ❌ Розыгрыш не найден " )
await state . clear ( )
return
removed = False
name = user_input
if user_input . startswith ( ' @ ' ) :
# Username
username = user_input [ 1 : ]
user = await UserService . get_user_by_username ( session , username )
if user :
removed = await ParticipationService . remove_participant ( session , lottery_id , user . id )
name = f " @ { user . username } " if user . username else f " { user . first_name } "
elif user_input . isdigit ( ) :
# Telegram ID
telegram_id = int ( user_input )
user = await UserService . get_user_by_telegram_id ( session , telegram_id )
if user :
removed = await ParticipationService . remove_participant ( session , lottery_id , user . id )
name = f " @ { user . username } " if user and user . username else f " ID: { telegram_id } "
elif ' - ' in user_input :
# Номер счета
from sqlalchemy import select , delete
from . . core . models import Participation
from src . utils . account_utils import parse_accounts_from_message
accounts = parse_accounts_from_message ( user_input )
if accounts :
account_number = accounts [ 0 ]
result = await session . execute (
select ( Participation ) . where (
Participation . lottery_id == lottery_id ,
Participation . account_number == account_number
)
)
participation = result . scalar_one_or_none ( )
if participation :
await session . delete ( participation )
await session . commit ( )
removed = True
name = f " Счет: { account_number } "
await state . clear ( )
if removed :
await message . answer (
f " ✅ Участник удалён! \n \n "
f " 👤 { name } \n "
f " 🎯 Розыгрыш: { lottery . title } " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ➖ Удалить ещё" , callback_data = f " admin_remove_from_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 👥 К участникам " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
else :
await message . answer (
f " ⚠️ Участник не найден в этом розыгрыше " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_participants_ { lottery_id } " ) ]
] )
)
# ======================
# ПРОВЕРКА ПОБЕДИТЕЛЕЙ И ПОВТОРНЫЙ РОЗЫГРЫШ
# ======================
@admin_router.callback_query ( F . data . startswith ( " admin_check_winners_ " ) )
async def check_winners ( callback : CallbackQuery ) :
""" Проверка подтверждения победителей """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
winners = await LotteryService . get_winners ( session , lottery_id )
if not winners :
await callback . message . edit_text (
f " 🏆 Проверка победителей \n \n "
f " 🎯 Розыгрыш: { lottery . title } \n \n "
f " ❌ Победители не определены. Сначала проведите розыгрыш. " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ]
] )
)
return
text = f " 🏆 Проверка победителей \n \n "
text + = f " 🎯 Розыгрыш: { lottery . title } \n \n "
confirmed_count = 0
unconfirmed_count = 0
for winner in winners :
status = " ✅ " if winner . is_claimed else " ⏳ "
if winner . is_claimed :
confirmed_count + = 1
else :
unconfirmed_count + = 1
# Определяем имя победителя
if winner . account_number :
name = f " Счет: { winner . account_number } "
elif winner . user :
name = f " @ { winner . user . username } " if winner . user . username else winner . user . first_name
else :
name = f " ID: { winner . user_id } "
# Приз
prize = lottery . prizes [ winner . place - 1 ] if lottery . prizes and len ( lottery . prizes ) > = winner . place else " Н е указан"
text + = f " { status } { winner . place } место: { name } \n "
text + = f " 🎁 Приз: { prize } \n "
if winner . is_claimed and winner . claimed_at :
text + = f " 📅 Подтверждено: { winner . claimed_at . strftime ( ' %d . % m. % Y % H: % M ' ) } \n "
text + = " \n "
text + = f " 📊 Итого: { confirmed_count } подтверждено, { unconfirmed_count } ожидает \n "
buttons = [ ]
if unconfirmed_count > 0 :
buttons . append ( [ InlineKeyboardButton ( text = " 🔄 Переиграть неподтверждённые " , callback_data = f " admin_redraw_ { lottery_id } " ) ] )
buttons . append ( [ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ] )
await callback . message . edit_text ( text , reply_markup = InlineKeyboardMarkup ( inline_keyboard = buttons ) )
@admin_router.callback_query ( F . data . startswith ( " admin_redraw_ " ) )
async def redraw_lottery ( callback : CallbackQuery ) :
""" Повторный розыгрыш для неподтверждённых призов """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
winners = await LotteryService . get_winners ( session , lottery_id )
# Находим неподтверждённых победителей
unconfirmed = [ w for w in winners if not w . is_claimed ]
if not unconfirmed :
await callback . answer ( " ✅ В с е победители подтверждены! " , show_alert = True )
return
# Показываем подтверждение
text = f " ⚠️ Повторный розыгрыш \n \n "
text + = f " 🎯 Розыгрыш: { lottery . title } \n \n "
text + = f " Будут переиграны { len ( unconfirmed ) } неподтверждённых мест: \n \n "
for winner in unconfirmed :
if winner . account_number :
name = f " Счет: { winner . account_number } "
elif winner . user :
name = f " @ { winner . user . username } " if winner . user . username else winner . user . first_name
else :
name = f " ID: { winner . user_id } "
prize = lottery . prizes [ winner . place - 1 ] if lottery . prizes and len ( lottery . prizes ) > = winner . place else " Н е указан"
text + = f " • { winner . place } место: { name } → { prize } \n "
text + = " \n ❗️ Эти счета будут исключены из повторного розыгрыша. "
await callback . message . edit_text (
text ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ✅ Подтвердить переигровку " , callback_data = f " admin_redraw_confirm_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " ❌ Отмена " , callback_data = f " admin_check_winners_ { lottery_id } " ) ]
] )
)
@admin_router.callback_query ( F . data . startswith ( " admin_redraw_confirm_ " ) )
async def confirm_redraw ( callback : CallbackQuery ) :
""" Подтверждение и выполнение повторного розыгрыша """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
await callback . answer ( " ⏳ Проводится повторный розыгрыш... " , show_alert = True )
async with async_session_maker ( ) as session :
from sqlalchemy import select , delete
from . . core . models import Winner , Participation
import random
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . message . edit_text ( " ❌ Розыгрыш не найден " )
return
winners = await LotteryService . get_winners ( session , lottery_id )
# Собираем подтверждённые и неподтверждённые
confirmed_winners = [ w for w in winners if w . is_claimed ]
unconfirmed_winners = [ w for w in winners if not w . is_claimed ]
if not unconfirmed_winners :
await callback . message . edit_text (
" ✅ В с е победители уже подтверждены! " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ]
] )
)
return
# Собираем исключённые счета (подтверждённые победители + бывшие неподтверждённые)
excluded_accounts = set ( )
for w in winners :
if w . account_number :
excluded_accounts . add ( w . account_number )
# Получаем всех участников, исключая уже выигравших
result = await session . execute (
select ( Participation )
. where ( Participation . lottery_id == lottery_id )
)
all_participations = result . scalars ( ) . all ( )
# Фильтруем участников
available_participations = [
p for p in all_participations
if p . account_number not in excluded_accounts
]
if not available_participations :
await callback . message . edit_text (
" ❌ Нет доступных участников для переигровки. \n "
" В с е участники уже выиграли или были исключены." ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🔙 Назад " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ]
] )
)
return
# Удаляем неподтверждённых победителей
for winner in unconfirmed_winners :
await session . delete ( winner )
# Проводим розыгрыш для неподтверждённых мест
new_winners_text = " "
random . shuffle ( available_participations )
for i , old_winner in enumerate ( unconfirmed_winners ) :
if i > = len ( available_participations ) :
break
new_participation = available_participations [ i ]
# Создаём нового победителя
new_winner = Winner (
lottery_id = lottery_id ,
user_id = new_participation . user_id ,
account_number = new_participation . account_number ,
place = old_winner . place ,
is_manual = False ,
is_claimed = False
)
session . add ( new_winner )
# Исключаем из следующих итераций
if new_participation . account_number :
excluded_accounts . add ( new_participation . account_number )
prize = lottery . prizes [ old_winner . place - 1 ] if lottery . prizes and len ( lottery . prizes ) > = old_winner . place else " Приз "
name = new_participation . account_number or f " ID: { new_participation . user_id } "
new_winners_text + = f " 🏆 { old_winner . place } место: { name } → { prize } \n "
await session . commit ( )
# Отправляем уведомления новым победителям
from . . utils . notifications import notify_winners_async
try :
await notify_winners_async ( callback . bot , session , lottery_id )
except Exception as e :
logger . error ( f " Ошибка при отправке уведомлений: { e } " )
text = f " 🎉 Повторный розыгрыш завершён! \n \n "
text + = f " 🎯 Розыгрыш: { lottery . title } \n \n "
text + = f " Новые победители: \n { new_winners_text } \n "
text + = " ✅ Уведомления отправлены новым победителям "
await callback . message . edit_text (
text ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " ✅ Проверить победителей " , callback_data = f " admin_check_winners_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " 🔙 К розыгрышу " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ]
] )
)
# ======================
# УДАЛЕНИЕ РОЗЫГРЫША
# ======================
@admin_router.callback_query ( F . data . startswith ( " admin_del_lottery_ " ) )
async def delete_lottery_confirm ( callback : CallbackQuery ) :
""" Подтверждение удаления розыгрыша """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
async with async_session_maker ( ) as session :
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
participants_count = await ParticipationService . get_participants_count ( session , lottery_id )
winners = await LotteryService . get_winners ( session , lottery_id )
text = f " ⚠️ Удаление розыгрыша \n \n "
text + = f " 🎯 Название: { lottery . title } \n "
text + = f " 👥 Участников: { participants_count } \n "
text + = f " 🏆 Победителей: { len ( winners ) } \n \n "
text + = " ❗️ Это действие необратимо! \n "
text + = " В с е данные о б участниках и победителях будут удалены."
await callback . message . edit_text (
text ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 🗑️ Да, удалить " , callback_data = f " admin_del_lottery_yes_ { lottery_id } " ) ] ,
[ InlineKeyboardButton ( text = " ❌ Отмена " , callback_data = f " admin_lottery_detail_ { lottery_id } " ) ]
] )
)
@admin_router.callback_query ( F . data . startswith ( " admin_del_lottery_yes_ " ) )
async def delete_lottery_execute ( callback : CallbackQuery ) :
""" Выполнение удаления розыгрыша """
if not is_admin ( callback . from_user . id ) :
await callback . answer ( " ❌ Недостаточно прав " , show_alert = True )
return
lottery_id = int ( callback . data . split ( " _ " ) [ - 1 ] )
async with async_session_maker ( ) as session :
from sqlalchemy import delete as sql_delete
from . . core . models import Winner , Participation
lottery = await LotteryService . get_lottery ( session , lottery_id )
if not lottery :
await callback . answer ( " ❌ Розыгрыш не найден " , show_alert = True )
return
lottery_title = lottery . title
# Удаляем победителей
await session . execute ( sql_delete ( Winner ) . where ( Winner . lottery_id == lottery_id ) )
# Удаляем участников
await session . execute ( sql_delete ( Participation ) . where ( Participation . lottery_id == lottery_id ) )
# Удаляем розыгрыш
await session . delete ( lottery )
await session . commit ( )
await callback . message . edit_text (
f " ✅ Розыгрыш удалён \n \n "
f " 🗑️ { lottery_title } " ,
reply_markup = InlineKeyboardMarkup ( inline_keyboard = [
[ InlineKeyboardButton ( text = " 📋 К списку розыгрышей " , callback_data = " admin_list_all_lotteries " ) ]
] )
)
# ======================
# М А С С О В О Е УПРАВЛЕНИЕ УЧАСТНИКАМИ ПО СЧЕТАМ
# ======================