from datetime import datetime, timedelta, timezone from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update from telegram.ext import ContextTypes from asgiref.sync import sync_to_async from hotels.models import Reservation, Hotel from users.models import User from bot.utils.pdf_report import generate_pdf_report from bot.utils.database import get_hotels_for_user, get_hotel_by_name from django.utils.timezone import make_aware async def statistics(update: Update, context: ContextTypes.DEFAULT_TYPE): """Вывод списка отелей для статистики.""" query = update.callback_query user_id = query.from_user.id await query.answer() # Получаем пользователя user = await sync_to_async(User.objects.filter(chat_id=user_id).first)() if not user: await query.edit_message_text("Вы не зарегистрированы в системе.") return # Получаем отели, связанные с пользователем user_hotels = await get_hotels_for_user(user) if not user_hotels: await query.edit_message_text("У вас нет доступных отелей для статистики.") return # Формируем кнопки для выбора отеля keyboard = [ [InlineKeyboardButton(hotel.hotel.name, callback_data=f"stats_hotel_{hotel.hotel.id}")] for hotel in user_hotels ] keyboard.append([InlineKeyboardButton("🏠 Главная", callback_data="main_menu")]) reply_markup = InlineKeyboardMarkup(keyboard) await query.edit_message_text("Выберите отель:", reply_markup=reply_markup) async def stats_select_period(update: Update, context: ContextTypes.DEFAULT_TYPE): """Выбор периода времени для статистики.""" query = update.callback_query await query.answer() hotel_id = int(query.data.split("_")[2]) context.user_data["selected_hotel"] = hotel_id keyboard = [ [InlineKeyboardButton("День", callback_data="stats_period_day")], [InlineKeyboardButton("Неделя", callback_data="stats_period_week")], [InlineKeyboardButton("Месяц", callback_data="stats_period_month")], [InlineKeyboardButton("Все время", callback_data="stats_period_all")], [InlineKeyboardButton("🏠 Главная", callback_data="main_menu")], [InlineKeyboardButton("🔙 Назад", callback_data="statistics")], ] reply_markup = InlineKeyboardMarkup(keyboard) await query.edit_message_text("Выберите период времени:", reply_markup=reply_markup) async def generate_statistics(update: Update, context: ContextTypes.DEFAULT_TYPE): """Генерация и отправка статистики.""" query = update.callback_query await query.answer() hotel_id = context.user_data.get("selected_hotel") if not hotel_id: await query.edit_message_text("Ошибка: ID отеля не найден.") return period = query.data.split("_")[2] print(f'Period raw: {query.data}') print(f'Selected period: {period}') now = datetime.utcnow().replace(tzinfo=timezone.utc) # Используем timezone.utc if period == "day": start_date = (now - timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0) end_date = now.replace(hour=23, minute=59, second=59, microsecond=999999) elif period == "week": start_date = (now - timedelta(days=7)).replace(hour=0, minute=0, second=0, microsecond=0) end_date = now.replace(hour=23, minute=59, second=59, microsecond=999999) elif period == "month": start_date = (now - timedelta(days=30)).replace(hour=0, minute=0, second=0, microsecond=0) end_date = now.replace(hour=23, minute=59, second=59, microsecond=999999) else: # "all" start_date = None end_date = None print(f'Raw start_date: {start_date}, Raw end_date: {end_date}') # Убедитесь, что даты имеют временную зону UTC if start_date: start_date = make_aware(start_date) if start_date.tzinfo is None else start_date if end_date: end_date = make_aware(end_date) if end_date.tzinfo is None else end_date print(f'Filtered start_date: {start_date}, Filtered end_date: {end_date}') # Фильтрация по "дата заезда" if start_date and end_date: reservations = await sync_to_async(list)( Reservation.objects.filter( hotel_id=hotel_id, check_in__gte=start_date, check_in__lte=end_date ).select_related('hotel') ) else: # Без фильтра по дате reservations = await sync_to_async(list)( Reservation.objects.filter( hotel_id=hotel_id ).select_related('hotel') ) print(f'Filtered reservations count: {len(reservations)}') if not reservations: await query.edit_message_text("Нет данных для статистики за выбранный период.") return hotel = await sync_to_async(Hotel.objects.get)(id=hotel_id) print(f'Hotel: {hotel.name}') for reservation in reservations: print(f"Reservation ID: {reservation.reservation_id}, Hotel: {reservation.hotel.name}, " f"Room number: {reservation.room_number}, Check-in: {reservation.check_in}, Check-out: {reservation.check_out}") # Генерация PDF отчета (пример) file_path = generate_pdf_report(hotel.name, reservations, start_date, end_date) print(f'Generated file path: {file_path}') with open(file_path, "rb") as file: await query.message.reply_document(document=file, filename=f"{hotel.name}_report.pdf") async def stats_back(update: Update, context): """Возврат к выбору отеля.""" query = update.callback_query await query.answer() # Получаем отели, связанные с пользователем user_id = query.from_user.id user = await sync_to_async(User.objects.filter(chat_id=user_id).first)() if not user: await query.edit_message_text("Ошибка: Пользователь не найден.") return hotels = await get_hotels_for_user(user) if not hotels: await query.edit_message_text("У вас нет доступных отелей.") return # Формируем кнопки для выбора отеля keyboard = [ [InlineKeyboardButton(hotel.name, callback_data=f"stats_hotel_{hotel.id}")] for hotel in hotels ] keyboard.append([InlineKeyboardButton("🏠 Главная", callback_data="main_menu")]) reply_markup = InlineKeyboardMarkup(keyboard) await query.edit_message_text("Выберите отель:", reply_markup=reply_markup)