bot upgraded

This commit is contained in:
2024-12-07 11:17:31 +09:00
parent e1c2ddbdb9
commit 66cf6ae940
8 changed files with 381 additions and 36 deletions

View File

@@ -1,7 +1,7 @@
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import ContextTypes
from users.models import User
from hotels.models import Hotel, UserHotel
from hotels.models import Hotel, UserHotel, Reservation
from users.models import NotificationSettings
from asgiref.sync import sync_to_async
import smtplib
@@ -9,7 +9,9 @@ from hotels.models import PMSIntegrationLog
import requests
from email.mime.text import MIMEText
from django.core.mail import send_mail
from datetime import datetime
from datetime import datetime, timedelta
from fpdf import FPDF
import os
# --- Вспомогательные функции ---
async def get_user_from_chat_id(chat_id):
@@ -78,9 +80,15 @@ async def manage_hotels(update: Update, context: ContextTypes.DEFAULT_TYPE):
async def handle_button_click(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработчик всех нажатий кнопок"""
query = update.callback_query
print(f"Обработчик кнопок: Получен callback_data = {query.data}")
await query.answer()
if query.data == "manage_hotels":
if query.data == "stats":
await statistics(update, context) # Добавляем вызов функции для обработки статистики
elif query.data.startswith("stats_hotel_"):
await stats_select_period(update, context)
elif query.data.startswith("stats_period_"):
await generate_statistics(update, context)
elif query.data == "manage_hotels":
await manage_hotels(update, context)
elif query.data.startswith("hotel_"):
await hotel_actions(update, context)
@@ -100,7 +108,6 @@ async def handle_button_click(update: Update, context: ContextTypes.DEFAULT_TYPE
await set_notification_time(update, context)
elif query.data == "current_settings":
await show_current_settings(update, context)
else:
print(f"Неизвестный callback_data: {query.data}")
await query.edit_message_text("Команда не распознана.")
@@ -433,3 +440,136 @@ async def check_pms_integration(update: Update, context: ContextTypes.DEFAULT_TY
message=str(e),
)
await query.edit_message_text(f"Произошла ошибка: {str(e)}")
async def get_hotels_for_user(user_id):
"""Получение отелей, связанных с пользователем."""
user = await sync_to_async(User.objects.filter(chat_id=user_id).first)()
if not user:
return []
return await sync_to_async(list)(
Hotel.objects.filter(userhotel__user=user).distinct()
)
async def get_reservations(hotel_id, start_date=None, end_date=None):
"""Получение статистики бронирований по отелю."""
query = Reservation.objects.filter(hotel_id=hotel_id)
if start_date:
query = query.filter(check_in__gte=start_date)
if end_date:
query = query.filter(check_out__lte=end_date)
return await sync_to_async(list)(query)
def generate_pdf_report(hotel_name, reservations, start_date, end_date):
"""Генерация PDF отчета."""
pdf = FPDF()
pdf.add_page()
# Подключение шрифта, поддерживающего кириллицу
font_path = os.path.join("fonts", "OpenSans-Regular.ttf")
print(f'\n\n\nПуть к шрифту: {font_path}\n\n\n') # Укажите путь к шрифту DejaVuSans.ttf
if not os.path.exists(font_path):
raise FileNotFoundError("Шрифт OpenSans-Regular.ttf не найден. Убедитесь, что он находится в папке 'fonts'.")
pdf.add_font("DejaVu", "", font_path, uni=True)
pdf.set_font("DejaVu", size=12)
# Заголовки
title = f"Отчет по заселениям: {hotel_name}"
period = (
f"Период: {start_date.strftime('%d.%m.%Y')} - {end_date.strftime('%d.%m.%Y')}"
if start_date and end_date
else "Период: Все время"
)
pdf.cell(200, 10, txt=title, ln=True, align="C")
pdf.cell(200, 10, txt=period, ln=True, align="C")
pdf.ln(10)
# Заголовки таблицы
pdf.set_font("DejaVu", size=10)
pdf.cell(40, 10, "Дата заезда", border=1)
pdf.cell(40, 10, "Дата выезда", border=1)
pdf.cell(30, 10, "Номер", border=1)
pdf.cell(50, 10, "Тип комнаты", border=1)
pdf.cell(30, 10, "Цена", border=1)
pdf.ln()
# Добавление данных
for res in reservations:
guests = ", ".join([guest.name for guest in res.guests.all()])
pdf.cell(40, 10, res.check_in.strftime('%d.%m.%Y'), border=1)
pdf.cell(40, 10, res.check_out.strftime('%d.%m.%Y'), border=1)
pdf.cell(30, 10, res.room_number, border=1)
pdf.cell(50, 10, res.room_type, border=1)
pdf.cell(30, 10, f"{res.price}", border=1)
pdf.ln()
pdf.multi_cell(200, 10, f"Гости: {guests}")
# Сохранение файла
file_path = os.path.join("reports", f"{hotel_name}_report.pdf")
os.makedirs(os.path.dirname(file_path), exist_ok=True)
pdf.output(file_path)
return file_path
# --- Обработчики ---
async def statistics(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Вывод списка отелей для статистики."""
query = update.callback_query
user_id = query.from_user.id
await query.answer()
hotels = await get_hotels_for_user(user_id)
if not hotels:
await query.edit_message_text("У вас нет доступных отелей для статистики.")
return
keyboard = [[InlineKeyboardButton(hotel.name, callback_data=f"stats_hotel_{hotel.id}")] for hotel in hotels]
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_week")],
[InlineKeyboardButton("Месяц", callback_data="stats_period_month")],
[InlineKeyboardButton("Все время", callback_data="stats_period_all")],
]
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["selected_hotel"]
period = query.data.split("_")[2]
now = datetime.now()
if period == "week":
start_date = now - timedelta(days=7)
end_date = now
elif period == "month":
start_date = now - timedelta(days=30)
end_date = now
else:
start_date = None
end_date = None
reservations = await get_reservations(hotel_id, start_date, end_date)
hotel = await sync_to_async(Hotel.objects.get)(id=hotel_id)
file_path = generate_pdf_report(hotel.name, reservations, start_date, end_date)
# Отправляем PDF файл пользователю
with open(file_path, "rb") as file:
await query.message.reply_document(document=file, filename=os.path.basename(file_path))