Files
Touchh/bot/operations/statistics.py
2024-12-14 08:34:35 +09:00

159 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)