# bot/handlers.py import re from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton from telegram.ext import ContextTypes from asgiref.sync import sync_to_async from webapp.models import BindingRequest, Client, Invoice from draw.models import Lottery, DrawResult, LotteryParticipant from bot.state import BINDING_PENDING @sync_to_async def get_client_by_telegram_id(telegram_id: int): try: return Client.objects.get(telegram_id=str(telegram_id)) except Client.DoesNotExist: return None @sync_to_async def get_invoices_for_client(client): return list(Invoice.objects.filter(client_club_card_number=client.club_card_number)) @sync_to_async def get_draws_for_client(client): return list( DrawResult.objects.filter(participant__invoice__client_club_card_number=client.club_card_number) .select_related('lottery', 'prize', 'participant__invoice') ) @sync_to_async def create_binding_request(telegram_chat_id, client_card): return BindingRequest.objects.create( telegram_chat_id=str(telegram_chat_id), client_card=client_card ) async def whoami(update: Update, context: ContextTypes.DEFAULT_TYPE): if not update.message: return chat_id = update.message.chat_id client = await get_client_by_telegram_id(chat_id) if not client: await update.message.reply_text( "❌ Пользователь не найден. Возможно, Вы ещё не привязали свою клубную карту." ) return invoices = await get_invoices_for_client(client) draws = await get_draws_for_client(client) message_text = f"👤 *Профиль клиента:*\n" \ f"• *Имя:* {client.name}\n" \ f"• *Клубная карта:* {client.club_card_number}\n\n" message_text += "💳 *Счета:*\n" if invoices: show_all = len(invoices) > 5 displayed_invoices = invoices[:5] if show_all else invoices for inv in displayed_invoices: invoice_str = str(inv).split('/')[0].strip() message_text += f" • {invoice_str} (*{inv.sum}*)\n" else: message_text += " _Нет счетов_\n" message_text += "\n🎉 *Розыгрыши и выигранные призы:*\n" if draws: for draw in draws: lottery_name = draw.lottery.name if draw.lottery else "неизвестно" invoice_info = (draw.participant.invoice if draw.participant and hasattr(draw.participant, 'invoice') else "неизвестно") prize_info = (draw.prize.reward if draw.prize and hasattr(draw.prize, 'reward') else "неизвестно") message_text += f" • Лотерея: *{lottery_name}*\n Счет: _{invoice_info}_\n Выигрыш: *{prize_info}*\n\n" else: message_text += " _Нет результатов розыгрышей_\n" reply_markup = None if invoices and len(invoices) > 5: reply_markup = InlineKeyboardMarkup([ [InlineKeyboardButton("Показать все счета", callback_data="show_all_invoices")] ]) await update.message.reply_text(message_text, parse_mode="Markdown", reply_markup=reply_markup) async def handle_client_card(update: Update, context: ContextTypes.DEFAULT_TYPE): """ Обработчик команды /bind. После ввода команды бот запрашивает ввод номера КК и ожидает сообщение с кодом. Здесь мы просто добавляем ID пользователя в pending. """ if not update.message: return telegram_chat_id = update.message.chat_id # Если пользователь уже привязан, сообщаем об этом. client = await get_client_by_telegram_id(telegram_chat_id) if client: await update.message.reply_text("✅ Вы уже привязаны!") return # Добавляем пользователя в список pending и просим ввести номер КК. BINDING_PENDING.add(telegram_chat_id) await update.message.reply_text("Введите номер вашей клубной карты (КК):") async def process_binding_input(update: Update, context: ContextTypes.DEFAULT_TYPE): """ Обрабатывает ввод номера КК от пользователя, который находится в состоянии ожидания. """ if not update.message or not update.message.text: return client_card = update.message.text.strip() telegram_chat_id = update.message.chat_id if not re.fullmatch(r'\d{3,}', client_card): await update.message.reply_text("❌ Неверный формат клиентской карты. Пожалуйста, введите корректный код (минимум 3 цифры).") return await create_binding_request(telegram_chat_id, client_card) if telegram_chat_id in BINDING_PENDING: BINDING_PENDING.remove(telegram_chat_id) await update.message.reply_text("✅ Заявка отправлена. После подтверждения вы сможете участвовать в чате.") async def show_all_invoices_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query await query.answer() chat_id = query.message.chat_id client = await get_client_by_telegram_id(chat_id) if not client: await query.edit_message_text("❌ Пользователь не найден. Возможно, Вы ещё не привязали свою клубную карту.") return invoices = await get_invoices_for_client(client) message_text = "💳 *Все счета:*\n" if invoices: for inv in invoices: invoice_str = str(inv).split('/')[0].strip() message_text += f" • {invoice_str} (*{inv.sum}*)\n" else: message_text += " _Нет счетов_\n" await query.edit_message_text(message_text, parse_mode="Markdown")