bot upgraded
This commit is contained in:
150
bot/handlers.py
150
bot/handlers.py
@@ -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))
|
||||
|
||||
BIN
bot/management/commands/fonts/OpenSans-Regular.ttf
Normal file
BIN
bot/management/commands/fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
@@ -25,6 +25,9 @@ from bot.handlers import (
|
||||
handle_notification_time,
|
||||
schedule_notifications,
|
||||
show_current_settings,
|
||||
statistics,
|
||||
generate_statistics,
|
||||
stats_select_period,
|
||||
)
|
||||
|
||||
# Настройка Django окружения
|
||||
@@ -53,6 +56,9 @@ async def start_bot(application):
|
||||
application.add_handler(CallbackQueryHandler(delete_hotel, pattern="^delete_hotel_"))
|
||||
application.add_handler(CallbackQueryHandler(check_pms, pattern="^check_pms_"))
|
||||
application.add_handler(CallbackQueryHandler(setup_rooms, pattern="^setup_rooms_"))
|
||||
application.add_handler(CallbackQueryHandler(statistics, pattern="^stats$"))
|
||||
application.add_handler(CallbackQueryHandler(stats_select_period, pattern="^stats_hotel_"))
|
||||
application.add_handler(CallbackQueryHandler(generate_statistics, pattern="^stats_period_"))
|
||||
|
||||
# Регистрация обработчиков текстовых сообщений
|
||||
print("Регистрация обработчиков текстовых сообщений...")
|
||||
|
||||
Reference in New Issue
Block a user